Convert to v2::security and adapt to ndn-cxx changes

Change-Id: I54f1b758cfb8f3f6cbc66a1aec5120ae1640b0ec
refs: #3964
diff --git a/.jenkins.d/01-ndn-cxx.sh b/.jenkins.d/01-ndn-cxx.sh
index 6eb84a5..c9e2a63 100755
--- a/.jenkins.d/01-ndn-cxx.sh
+++ b/.jenkins.d/01-ndn-cxx.sh
@@ -18,37 +18,29 @@
     fi
 fi
 
-## Uncomment when #3920 and #4119 merge.
-# if [[ -z $INSTALLED_VERSION ]]; then
-#     INSTALLED_VERSION=$(git -C ndn-cxx rev-parse HEAD 2>/dev/null || echo NONE)
-# fi
+if [[ -z $INSTALLED_VERSION ]]; then
+    INSTALLED_VERSION=$(git -C ndn-cxx rev-parse HEAD 2>/dev/null || echo NONE)
+fi
 
 sudo rm -Rf ndn-cxx-latest
-## Remove this when #3920 and #4119 merge
-sudo rm -Rf ndn-cxx-hotfix
-git clone git://github.com/named-data/ndn-cxx ndn-cxx-hotfix
 
-## Uncomment when #3920 and #4119 merge.
-# LATEST_VERSION=$(git -C ndn-cxx-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN)
+git clone --depth 1 git://github.com/named-data/ndn-cxx ndn-cxx-latest
 
-# if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then
-#     sudo rm -Rf ndn-cxx
-#     mv ndn-cxx-latest ndn-cxx
-#     cp ndn-cxx ndn-cxx-hotfix
-# else
-#     sudo rm -Rf ndn-cxx-latest
-# fi
+LATEST_VERSION=$(git -C ndn-cxx-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN)
+
+if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then
+    sudo rm -Rf ndn-cxx
+    mv ndn-cxx-latest ndn-cxx
+else
+    sudo rm -Rf ndn-cxx-latest
+fi
 
 sudo rm -f /usr/local/bin/ndnsec*
 sudo rm -fr /usr/local/include/ndn-cxx
 sudo rm -f /usr/local/lib/libndn-cxx*
 sudo rm -f /usr/local/lib/pkgconfig/libndn-cxx.pc
 
-## Change to the hotfix directory instead of the normal ndn-cxx directory
-## Restore below line when #3920 and #4119 merge.
-#pushd ndn-cxx >/dev/null
-pushd ndn-cxx-hotfix >/dev/null
-git checkout b555b00c280b9c9ed46f24a1fbebc73b720601af
+pushd ndn-cxx >/dev/null
 
 ./waf configure --color=yes --enable-shared --disable-static --without-osx-keychain
 ./waf build --color=yes -j${WAF_JOBS:-1}
diff --git a/.jenkins.d/02-chronosync.sh b/.jenkins.d/02-chronosync.sh
index aa8c875..82145f6 100755
--- a/.jenkins.d/02-chronosync.sh
+++ b/.jenkins.d/02-chronosync.sh
@@ -18,30 +18,28 @@
     fi
 fi
 
-# if [[ -z $INSTALLED_VERSION ]]; then
-#     INSTALLED_VERSION=$(git -C ChronoSync rev-parse HEAD 2>/dev/null || echo NONE)
-# fi
+if [[ -z $INSTALLED_VERSION ]]; then
+    INSTALLED_VERSION=$(git -C ChronoSync rev-parse HEAD 2>/dev/null || echo NONE)
+fi
 
 sudo rm -Rf ChronoSync-latest
-## Remove line when #3920 and #4119 merge.
-sudo rm -rf ChronoSync-hotfix
-git clone git://github.com/named-data/ChronoSync ChronoSync-hotfix
 
-# LATEST_VERSION=$(git -C ChronoSync-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN)
+git clone --depth 1 git://github.com/named-data/ChronoSync ChronoSync-latest
 
-# if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then
-#     sudo rm -Rf ChronoSync
-#     mv ChronoSync-latest ChronoSync
-# else
-#     sudo rm -Rf ChronoSync-latest
-# fi
+LATEST_VERSION=$(git -C ChronoSync-latest rev-parse HEAD 2>/dev/null || echo UNKNOWN)
+
+if [[ $INSTALLED_VERSION != $LATEST_VERSION ]]; then
+    sudo rm -Rf ChronoSync
+    mv ChronoSync-latest ChronoSync
+else
+    sudo rm -Rf ChronoSync-latest
+fi
 
 sudo rm -fr /usr/local/include/ChronoSync
 sudo rm -f /usr/local/lib/libChronoSync*
 sudo rm -f /usr/local/lib/pkgconfig/ChronoSync*
 
-pushd ChronoSync-hotfix >/dev/null
-git checkout 097bb448f46b8bd9a5c1f431e824f8f6a169b650
+pushd ChronoSync >/dev/null
 
 if has FreeBSD10 $NODE_LABELS; then
     export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/
diff --git a/docs/redmine_issue.py b/docs/redmine_issue.py
index e80c036..0df2b1f 100644
--- a/docs/redmine_issue.py
+++ b/docs/redmine_issue.py
@@ -50,8 +50,8 @@
         base = app.config.redmine_project_url
         if not base:
             raise AttributeError
-    except AttributeError, err:
-        raise ValueError('redmine_project_url configuration value is not set (%s)' % str(err))
+    except AttributeError:
+        raise ValueError('redmine_project_url configuration value is not set')
     #
     slash = '/' if base[-1] != '/' else ''
     ref = base + slash + type + '/' + slug + '/'
@@ -67,4 +67,4 @@
     """
     app.add_role('issue', redmine_role)
     app.add_config_value('redmine_project_url', None, 'env')
-    return
\ No newline at end of file
+    return
diff --git a/nlsr.conf b/nlsr.conf
index ef569ce..378f63c 100644
--- a/nlsr.conf
+++ b/nlsr.conf
@@ -68,7 +68,7 @@
   face-dataset-fetch-tries 3 ; default is 3. Valid values 1-10. The FaceDataset is
                              ; gotten from NFD, and is needed to configure NLSR
                              ; correctly. It is recommended not to set this
-                             : variable too high, because it could cause
+                             ; variable too high, because it could cause
                              ; congestion for NFD.
 
   face-dataset-fetch-interval 3600 ; default is 3600. Valid values 1800-5400.
@@ -166,7 +166,7 @@
           type name
           hyper-relation
           {
-            k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
+            k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><>$
             k-expand \\1
             h-relation equal
             p-regex ^([^<NLSR><INFO>]*)<NLSR><INFO><><>$
@@ -194,7 +194,7 @@
           type name
           hyper-relation
           {
-            k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$
+            k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><>$
             k-expand \\1
             h-relation equal
             ; the last four components in the prefix should be <lsaType><seqNo><version><segmentNo>
@@ -212,7 +212,7 @@
       filter
       {
         type name
-        regex ^[^<KEY><%C1.Router>]*<%C1.Router>[^<KEY><NLSR>]*<KEY><ksk-.*><ID-CERT><>$
+        regex ^[^<KEY><%C1.Router>]*<%C1.Router>[^<KEY><NLSR>]*<KEY><><><>$
       }
       checker
       {
@@ -223,10 +223,10 @@
           type name
           hyper-relation
           {
-            k-regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$
+            k-regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><>$
             k-expand \\1
             h-relation equal
-            p-regex ^([^<KEY><%C1.Router>]*)<%C1.Router>[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
+            p-regex ^([^<KEY><%C1.Router>]*)<%C1.Router>[^<KEY>]*<KEY><><><>$
             p-expand \\1
           }
         }
@@ -240,7 +240,7 @@
       filter
       {
         type name
-        regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
+        regex ^[^<KEY>]*<KEY><><><>$
       }
       checker
       {
@@ -265,7 +265,9 @@
       filter
       {
         type name
-        regex ^<localhost><nlsr><prefix-update>[<advertise><withdraw>]<>$
+        ; /<prefix>/<management-module>/<command-verb>/<control-parameters>
+        ; /<timestamp>/<random-value>/<signed-interests-components>
+        regex ^<localhost><nlsr><prefix-update>[<advertise><withdraw>]<><><>$
       }
       checker
       {
@@ -274,7 +276,7 @@
         key-locator
         {
           type name
-          regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$
+          regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><>$
         }
       }
     }
@@ -286,7 +288,7 @@
       filter
       {
         type name
-        regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$
+        regex ^[^<KEY>]*<KEY><><><>$
       }
       checker
       {
@@ -301,6 +303,7 @@
       file-name "site.cert"
     }
   }
+
   ; cert-to-publish "root.cert"  ; optional, a file containing the root certificate
                                  ; Only the router that is designated to publish the root cert
                                  ; needs to specify this
diff --git a/src/adjacency-list.cpp b/src/adjacency-list.cpp
index 33626f5..9d02d7e 100644
--- a/src/adjacency-list.cpp
+++ b/src/adjacency-list.cpp
@@ -266,7 +266,7 @@
 }
 
 AdjacencyList::iterator
-AdjacencyList::findAdjacent(const ndn::util::FaceUri& faceUri)
+AdjacencyList::findAdjacent(const ndn::FaceUri& faceUri)
 {
   return std::find_if(m_adjList.begin(),
                       m_adjList.end(),
@@ -275,7 +275,7 @@
 }
 
 uint64_t
-AdjacencyList::getFaceId(const ndn::util::FaceUri& faceUri)
+AdjacencyList::getFaceId(const ndn::FaceUri& faceUri)
 {
   std::list<Adjacent>::iterator it = std::find_if(m_adjList.begin(),
                                                   m_adjList.end(),
diff --git a/src/adjacency-list.hpp b/src/adjacency-list.hpp
index 6b8ea64..6d37a94 100644
--- a/src/adjacency-list.hpp
+++ b/src/adjacency-list.hpp
@@ -149,7 +149,7 @@
   findAdjacent(uint64_t faceId);
 
   AdjacencyList::iterator
-  findAdjacent(const ndn::util::FaceUri& faceUri);
+  findAdjacent(const ndn::FaceUri& faceUri);
 
   /*! \brief Hack to stop developers from using this function
 
@@ -165,7 +165,7 @@
   }
 
   uint64_t
-  getFaceId(const ndn::util::FaceUri& faceUri);
+  getFaceId(const ndn::FaceUri& faceUri);
 
   void
   writeLog();
diff --git a/src/adjacent.cpp b/src/adjacent.cpp
index 913bbbd..0476878 100644
--- a/src/adjacent.cpp
+++ b/src/adjacent.cpp
@@ -52,7 +52,7 @@
   {
   }
 
-Adjacent::Adjacent(const ndn::Name& an, const ndn::util::FaceUri& faceUri,  double lc,
+Adjacent::Adjacent(const ndn::Name& an, const ndn::FaceUri& faceUri,  double lc,
                    Status s, uint32_t iton, uint64_t faceId)
     : m_name(an)
     , m_faceUri(faceUri)
diff --git a/src/adjacent.hpp b/src/adjacent.hpp
index dcdefc8..1e6eac5 100644
--- a/src/adjacent.hpp
+++ b/src/adjacent.hpp
@@ -23,7 +23,7 @@
 #include <boost/cstdint.hpp>
 
 #include <ndn-cxx/face.hpp>
-#include <ndn-cxx/util/face-uri.hpp>
+#include <ndn-cxx/net/face-uri.hpp>
 
 #ifndef NLSR_ADJACENT_HPP
 #define NLSR_ADJACENT_HPP
@@ -50,7 +50,7 @@
 
   Adjacent(const ndn::Name& an);
 
-  Adjacent(const ndn::Name& an, const ndn::util::FaceUri& faceUri, double lc,
+  Adjacent(const ndn::Name& an, const ndn::FaceUri& faceUri, double lc,
            Status s, uint32_t iton, uint64_t faceId);
 
   const ndn::Name&
@@ -65,14 +65,14 @@
     m_name = an;
   }
 
-  const ndn::util::FaceUri&
+  const ndn::FaceUri&
   getFaceUri() const
   {
     return m_faceUri;
   }
 
   void
-  setFaceUri(const ndn::util::FaceUri& faceUri)
+  setFaceUri(const ndn::FaceUri& faceUri)
   {
     m_faceUri = faceUri;
   }
@@ -152,7 +152,7 @@
   }
 
   inline bool
-  compareFaceUri(const ndn::util::FaceUri& faceUri)
+  compareFaceUri(const ndn::FaceUri& faceUri)
   {
     return m_faceUri == faceUri;
   }
@@ -166,8 +166,8 @@
 private:
   /*! m_name The NLSR-configured router name of the neighbor */
   ndn::Name m_name;
-  /*! m_connectingFaceUri The NFD-level specification of the Face*/
-  ndn::util::FaceUri m_faceUri;
+  /*! m_faceUri The NFD-level specification of the Face*/
+  ndn::FaceUri m_faceUri;
   /*! m_linkCost The semi-arbitrary cost to traverse the link. */
   double m_linkCost;
   /*! m_status Whether the neighbor is active or not */
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index 8359d37..d13b415 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -28,7 +28,7 @@
 #include <boost/cstdint.hpp>
 
 #include <ndn-cxx/name.hpp>
-#include <ndn-cxx/util/face-uri.hpp>
+#include <ndn-cxx/net/face-uri.hpp>
 
 #include <iostream>
 #include <fstream>
@@ -496,7 +496,7 @@
         std::string name = CommandAttriTree.get<std::string>("name");
         std::string uriString = CommandAttriTree.get<std::string>("face-uri");
 
-        ndn::util::FaceUri faceUri;
+        ndn::FaceUri faceUri;
         if (! faceUri.parse(uriString)) {
           std::cerr << "parsing failed!" << std::endl;
           return false;
@@ -665,15 +665,15 @@
 
       std::string file = it->second.data();
       path certfilePath = absolute(file, path(m_confFileName).parent_path());
-      std::shared_ptr<ndn::IdentityCertificate> idCert =
-        ndn::io::load<ndn::IdentityCertificate>(certfilePath.string());
+      std::shared_ptr<ndn::security::v2::Certificate> idCert =
+        ndn::io::load<ndn::security::v2::Certificate>(certfilePath.string());
 
       if (idCert == nullptr) {
         std::cerr << "Error: Cannot load cert-to-publish: " << file << "!" << std::endl;
         return false;
       }
 
-      m_nlsr.loadCertToPublish(idCert);
+      m_nlsr.loadCertToPublish(*idCert);
     }
   }
 
diff --git a/src/hello-protocol.cpp b/src/hello-protocol.cpp
index b28620b..fbb4f5b 100644
--- a/src/hello-protocol.cpp
+++ b/src/hello-protocol.cpp
@@ -114,8 +114,11 @@
     data->setFreshnessPeriod(ndn::time::seconds(10)); // 10 sec
     data->setContent(reinterpret_cast<const uint8_t*>(INFO_COMPONENT.c_str()),
                     INFO_COMPONENT.size());
-    m_nlsr.getKeyChain().sign(*data, m_nlsr.getDefaultCertName());
+
+    m_nlsr.getKeyChain().sign(*data, m_nlsr.getSigningInfo());
+
     NLSR_LOG_DEBUG("Sending out data for name: " << interest.getName());
+
     m_nlsr.getNlsrFace().put(*data);
     // increment SENT_HELLO_DATA
     hpIncrementSignal(Statistics::PacketType::SENT_HELLO_DATA);
@@ -195,11 +198,12 @@
 }
 
 void
-HelloProtocol::onContentValidated(const std::shared_ptr<const ndn::Data>& data)
+HelloProtocol::onContentValidated(const ndn::Data& data)
 {
   // data name: /<neighbor>/NLSR/INFO/<router>/<version>
-  ndn::Name dataName = data->getName();
+  ndn::Name dataName = data.getName();
   NLSR_LOG_DEBUG("Data validation successful for INFO(name): " << dataName);
+
   if (dataName.get(-3).toUri() == INFO_COMPONENT) {
     ndn::Name neighbor = dataName.getPrefix(-4);
 
@@ -225,10 +229,10 @@
 }
 
 void
-HelloProtocol::onContentValidationFailed(const std::shared_ptr<const ndn::Data>& data,
-                                         const std::string& msg)
+HelloProtocol::onContentValidationFailed(const ndn::Data& data,
+                                         const ndn::security::v2::ValidationError& ve)
 {
-  NLSR_LOG_DEBUG("Validation Error: " << msg);
+  NLSR_LOG_DEBUG("Validation Error: " << ve);
 }
 
 } // namespace nlsr
diff --git a/src/hello-protocol.hpp b/src/hello-protocol.hpp
index c042707..ae95a0e 100644
--- a/src/hello-protocol.hpp
+++ b/src/hello-protocol.hpp
@@ -30,6 +30,7 @@
 #include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
 #include <ndn-cxx/mgmt/nfd/control-response.hpp>
 #include <ndn-cxx/util/scheduler.hpp>
+#include <ndn-cxx/security/v2/validation-error.hpp>
 
 namespace nlsr {
 
@@ -128,14 +129,14 @@
    * to contact this neighbor so that we will retry later.
    */
   void
-  onContentValidated(const std::shared_ptr<const ndn::Data>& data);
+  onContentValidated(const ndn::Data& data);
 
 private:
   /*! \brief Log that incoming data couldn't be validated, but do nothing else.
    */
   void
-  onContentValidationFailed(const std::shared_ptr<const ndn::Data>& data,
-                            const std::string& msg);
+  onContentValidationFailed(const ndn::Data& data,
+                            const ndn::security::v2::ValidationError& ve);
 
   /*! \brief Treat a failed Face registration as an INACTIVE neighbor.
    *
diff --git a/src/lsa.cpp b/src/lsa.cpp
index 5c2cc7a..91f6a7a 100644
--- a/src/lsa.cpp
+++ b/src/lsa.cpp
@@ -248,7 +248,7 @@
       ndn::Name adjName(*tok_iter++);
       std::string connectingFaceUri(*tok_iter++);
       double linkCost = boost::lexical_cast<double>(*tok_iter++);
-      Adjacent adjacent(adjName, ndn::util::FaceUri(connectingFaceUri), linkCost,
+      Adjacent adjacent(adjName, ndn::FaceUri(connectingFaceUri), linkCost,
                         Adjacent::STATUS_INACTIVE, 0, 0);
       addAdjacent(adjacent);
     }
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index 9efc733..6df2346 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -38,9 +38,10 @@
 public:
   LsaContentPublisher(ndn::Face& face,
                       ndn::KeyChain& keyChain,
+                      const ndn::security::SigningInfo& signingInfo,
                       const ndn::time::milliseconds& freshnessPeriod,
                       const std::string& content)
-    : SegmentPublisher(face, keyChain, freshnessPeriod)
+    : SegmentPublisher(face, keyChain, signingInfo, freshnessPeriod)
     , m_content(content)
   {
   }
@@ -1073,12 +1074,12 @@
 {
   LsaContentPublisher publisher(m_nlsr.getNlsrFace(),
                                 m_nlsr.getKeyChain(),
+                                m_nlsr.getSigningInfo(),
                                 m_lsaRefreshTime,
                                 content);
   NLSR_LOG_DEBUG("Sending requested data ( " << content << ")  for interest (" << interest
              << ") to be published and added to face.");
-  publisher.publish(interest.getName(),
-                    ndn::security::signingByCertificate(m_nlsr.getDefaultCertName()));
+  publisher.publish(interest.getName());
 }
 
   // \brief Finds and sends a requested name LSA.
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index da9de61..296c5e0 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -29,7 +29,8 @@
 #include <cstdio>
 #include <unistd.h>
 
-#include <ndn-cxx/util/face-uri.hpp>
+#include <ndn-cxx/net/face-uri.hpp>
+#include <ndn-cxx/signature.hpp>
 
 namespace nlsr {
 
@@ -61,20 +62,14 @@
                          m_routerNameDispatcher,
                          m_nlsrFace,
                          m_keyChain)
-
   , m_helloProtocol(*this, scheduler)
-  , m_certificateCache(new ndn::CertificateCacheTtl(ioService))
-  , m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache, m_certStore)
-  , m_controller(m_nlsrFace, m_keyChain, m_validator)
+  , m_validator(ndn::make_unique<ndn::security::v2::CertificateFetcherDirectFetch>(m_nlsrFace))
+  , m_controller(m_nlsrFace, m_keyChain)
   , m_faceDatasetController(m_nlsrFace, m_keyChain)
   , m_prefixUpdateProcessor(m_localhostDispatcher,
                             m_nlsrFace,
                             m_namePrefixList,
-                            m_nlsrLsdb,
-                            DEFAULT_BROADCAST_PREFIX,
-                            m_keyChain,
-                            m_certificateCache,
-                            m_certStore)
+                            m_nlsrLsdb)
   , m_nfdRibCommandProcessor(m_localhostDispatcher,
                              m_namePrefixList,
                              m_nlsrLsdb)
@@ -97,36 +92,17 @@
 Nlsr::onRegistrationSuccess(const ndn::Name& name)
 {
   NLSR_LOG_DEBUG("Successfully registered prefix: " << name);
-
-  if (name.equals(m_confParam.getRouterPrefix())) {
-    // the top-level prefixes are added.
-    try {
-      m_routerNameDispatcher.addTopPrefix(m_confParam.getRouterPrefix(), false, m_signingInfo);
-    }
-    catch (const std::exception& e) {
-      NLSR_LOG_ERROR("Error setting top-level prefix in dispatcher: " << e.what() << "\n");
-    }
-  }
-}
-
-void
-Nlsr::onLocalhostRegistrationSuccess(const ndn::Name& name)
-{
-  // All dispatcher-related sub-prefixes *must* be registered before
-  // the top-level prefixes are added.
-  try {
-    m_localhostDispatcher.addTopPrefix(LOCALHOST_PREFIX, false, m_signingInfo);
-  }
-  catch (const std::exception& e) {
-    NLSR_LOG_ERROR("Error setting top-level prefix in dispatcher: " << e.what() << "\n");
-  }
 }
 
 void
 Nlsr::setInfoInterestFilter()
 {
   ndn::Name name(m_confParam.getRouterPrefix());
-  NLSR_LOG_DEBUG("Setting interest filter for name: " << name);
+  name.append("NLSR");
+  name.append("INFO");
+
+  NLSR_LOG_DEBUG("Setting interest filter for Hello interest: " << name);
+
   getNlsrFace().setInterestFilter(name,
                                   std::bind(&HelloProtocol::processInterest,
                                             &m_helloProtocol, _1, _2),
@@ -142,7 +118,9 @@
   ndn::Name name = m_confParam.getLsaPrefix();
   name.append(m_confParam.getSiteName());
   name.append(m_confParam.getRouterName());
+
   NLSR_LOG_DEBUG("Setting interest filter for LsaPrefix: " << name);
+
   getNlsrFace().setInterestFilter(name,
                                   std::bind(&Lsdb::processInterest,
                                             &m_nlsrLsdb, _1, _2),
@@ -152,16 +130,29 @@
                                   ndn::nfd::ROUTE_FLAG_CAPTURE);
 }
 
+
+void
+Nlsr::addDispatcherTopPrefix(const ndn::Name& topPrefix)
+{
+  try {
+    if (topPrefix.equals(m_confParam.getRouterPrefix())) {
+      m_routerNameDispatcher.addTopPrefix(topPrefix, false, m_signingInfo);
+    }
+    else {
+      m_localhostDispatcher.addTopPrefix(topPrefix, false, m_signingInfo);
+    }
+  }
+  catch (const std::exception& e) {
+    NLSR_LOG_ERROR("Error setting top-level prefix in dispatcher: " << e.what() << "\n");
+  }
+}
+
 void
 Nlsr::setStrategies()
 {
   const std::string strategy("ndn:/localhost/nfd/strategy/multicast");
 
-  ndn::Name broadcastKeyPrefix = DEFAULT_BROADCAST_PREFIX;
-  broadcastKeyPrefix.append("KEYS");
-
   m_fib.setStrategy(m_confParam.getLsaPrefix(), strategy, 0);
-  m_fib.setStrategy(broadcastKeyPrefix, strategy, 0);
   m_fib.setStrategy(m_confParam.getChronosyncPrefix(), strategy, 0);
 }
 
@@ -207,8 +198,8 @@
                            std::function<void(void)> finally)
 {
   if (currentNeighbor != m_adjacencyList.getAdjList().end()) {
-    ndn::util::FaceUri uri(currentNeighbor->getFaceUri());
-    uri.canonize([this, then, currentNeighbor] (ndn::util::FaceUri canonicalUri) {
+    ndn::FaceUri uri(currentNeighbor->getFaceUri());
+    uri.canonize([this, then, currentNeighbor] (ndn::FaceUri canonicalUri) {
         NLSR_LOG_DEBUG("Canonized URI: " << currentNeighbor->getFaceUri()
                    << " to: " << canonicalUri);
         currentNeighbor->setFaceUri(canonicalUri);
@@ -228,6 +219,18 @@
   }
 }
 
+
+void
+Nlsr::loadCertToPublish(const ndn::security::v2::Certificate& certificate)
+{
+  m_certStore.insert(certificate);
+  m_validator.loadAnchor("Authoritative-Certificate",
+                          ndn::security::v2::Certificate(certificate));
+  m_prefixUpdateProcessor.getValidator().
+                          loadAnchor("Authoritative-Certificate",
+                                      ndn::security::v2::Certificate(certificate));
+}
+
 void
 Nlsr::initialize()
 {
@@ -248,15 +251,24 @@
   m_adjacencyList.writeLog();
   NLSR_LOG_DEBUG(m_namePrefixList);
   // Logging end
+
   initializeKey();
   setStrategies();
+
   NLSR_LOG_DEBUG("Default NLSR identity: " << m_signingInfo.getSignerName());
+
   setInfoInterestFilter();
   setLsaInterestFilter();
 
+  // add top-level prefixes: router and localhost prefix
+  addDispatcherTopPrefix(m_confParam.getRouterPrefix());
+  addDispatcherTopPrefix(LOCALHOST_PREFIX);
+
   initializeFaces(std::bind(&Nlsr::processFaceDataset, this, _1),
                   std::bind(&Nlsr::onFaceDatasetFetchTimeout, this, _1, _2, 0));
 
+  enableIncomingFaceIdIndication();
+
   // Set event intervals
   setFirstHelloInterval(m_confParam.getFirstHelloInterval());
   m_nlsrLsdb.setAdjLsaBuildInterval(m_confParam.getAdjLsaBuildInterval());
@@ -288,44 +300,71 @@
 void
 Nlsr::initializeKey()
 {
-  ndn::Name defaultIdentity = m_confParam.getRouterPrefix();
-  defaultIdentity.append("NLSR");
+  NLSR_LOG_DEBUG("Initializing Key ...");
+
+  ndn::Name nlsrInstanceName = m_confParam.getRouterPrefix();
+  nlsrInstanceName.append("NLSR");
 
   try {
-    m_keyChain.deleteIdentity(defaultIdentity);
+    m_keyChain.deleteIdentity(m_keyChain.getPib().getIdentity(nlsrInstanceName));
+  } catch (const std::exception& e) {
+    NLSR_LOG_WARN(e.what());
+  }
+
+  auto nlsrInstanceIdentity = m_keyChain.createIdentity(nlsrInstanceName);
+  auto nlsrInstanceKey = nlsrInstanceIdentity.getDefaultKey();
+
+  ndn::security::v2::Certificate certificate;
+
+  ndn::Name certificateName = nlsrInstanceKey.getName();
+  certificateName.append("NA");
+  certificateName.appendVersion();
+  certificate.setName(certificateName);
+
+  // set metainfo
+  certificate.setContentType(ndn::tlv::ContentType_Key);
+  certificate.setFreshnessPeriod(ndn::time::days(7300));
+
+  // set content
+  certificate.setContent(nlsrInstanceKey.getPublicKey().data(), nlsrInstanceKey.getPublicKey().size());
+
+  // set signature-info
+  ndn::SignatureInfo signatureInfo;
+  signatureInfo.setValidityPeriod(ndn::security::ValidityPeriod(ndn::time::system_clock::TimePoint(),
+                                                                ndn::time::system_clock::now()
+                                                                + ndn::time::days(20 * 365)));
+  try {
+    m_keyChain.sign(certificate,
+                    ndn::security::SigningInfo(m_keyChain.getPib().getIdentity(m_confParam.getRouterPrefix()))
+                                               .setSignatureInfo(signatureInfo));
   }
   catch (const std::exception& e) {
+    NLSR_LOG_WARN("ERROR: Router's " << e.what()
+                  << "NLSR is running without security."
+                  << " If security is enabled NLSR will not converge.");
+
+    std::cerr << "Router's " << e.what() << "NLSR is running without security "
+              << "(Only for testing, should not be used in production.)"
+              << " If security is enabled NLSR will not converge." << std::endl;
   }
-  m_signingInfo = ndn::security::SigningInfo(ndn::security::SigningInfo::SIGNER_TYPE_ID, defaultIdentity);
 
-  ndn::Name keyName = m_keyChain.generateRsaKeyPairAsDefault(defaultIdentity, true);
+  m_signingInfo = ndn::security::SigningInfo(ndn::security::SigningInfo::SIGNER_TYPE_ID,
+                                             nlsrInstanceName);
 
-  std::shared_ptr<ndn::IdentityCertificate> certificate =
-    std::make_shared<ndn::IdentityCertificate>();
-  std::shared_ptr<ndn::PublicKey> pubKey = m_keyChain.getPublicKey(keyName);
-  ndn::Name certificateName = keyName.getPrefix(-1);
-  certificateName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
-  certificate->setName(certificateName);
-  certificate->setNotBefore(ndn::time::system_clock::now() - ndn::time::days(1));
-  certificate->setNotAfter(ndn::time::system_clock::now() + ndn::time::days(7300)); // ~20 years
-  certificate->setPublicKeyInfo(*pubKey);
-  certificate->addSubjectDescription(ndn::CertificateSubjectDescription(ndn::oid::ATTRIBUTE_NAME,
-                                                                   keyName.toUri()));
-  certificate->encode();
-  m_keyChain.signByIdentity(*certificate, m_confParam.getRouterPrefix());
-
-  m_keyChain.addCertificateAsIdentityDefault(*certificate);
   loadCertToPublish(certificate);
 
-  m_defaultCertName = certificate->getName();
+  m_defaultCertName = certificate.getName();
 }
 
 void
 Nlsr::registerKeyPrefix()
 {
-  ndn::Name keyPrefix = DEFAULT_BROADCAST_PREFIX;
-  keyPrefix.append("KEYS");
-  m_nlsrFace.setInterestFilter(keyPrefix,
+  // Start listening for the interest of this router's NLSR certificate
+  ndn::Name nlsrKeyPrefix = getConfParameter().getRouterPrefix();
+  nlsrKeyPrefix.append("NLSR");
+  nlsrKeyPrefix.append("KEY");
+
+  m_nlsrFace.setInterestFilter(nlsrKeyPrefix,
                                std::bind(&Nlsr::onKeyInterest,
                                          this, _1, _2),
                                std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
@@ -333,52 +372,73 @@
                                m_signingInfo,
                                ndn::nfd::ROUTE_FLAG_CAPTURE);
 
+  // Start listening for the interest of this router's certificate
+  ndn::Name routerKeyPrefix = getConfParameter().getRouterPrefix();
+  routerKeyPrefix.append("KEY");
+
+  m_nlsrFace.setInterestFilter(routerKeyPrefix,
+                                 std::bind(&Nlsr::onKeyInterest,
+                                           this, _1, _2),
+                                 std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
+                                 std::bind(&Nlsr::registrationFailed, this, _1),
+                                 m_signingInfo,
+                                 ndn::nfd::ROUTE_FLAG_CAPTURE);
+
+  // Start listening for the interest of this router's operator's certificate
+  ndn::Name operatorKeyPrefix = getConfParameter().getNetwork();
+  operatorKeyPrefix.append(getConfParameter().getSiteName());
+  operatorKeyPrefix.append(std::string("%C1.Operator"));
+
+  m_nlsrFace.setInterestFilter(operatorKeyPrefix,
+                               std::bind(&Nlsr::onKeyInterest,
+                                         this, _1, _2),
+                               std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
+                               std::bind(&Nlsr::registrationFailed, this, _1),
+                               m_signingInfo,
+                               ndn::nfd::ROUTE_FLAG_CAPTURE);
+
+  // Start listening for the interest of this router's site's certificate
+  ndn::Name siteKeyPrefix = getConfParameter().getNetwork();
+  siteKeyPrefix.append(getConfParameter().getSiteName());
+  siteKeyPrefix.append("KEY");
+
+  m_nlsrFace.setInterestFilter(siteKeyPrefix,
+                               std::bind(&Nlsr::onKeyInterest,
+                                          this, _1, _2),
+                               std::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
+                               std::bind(&Nlsr::registrationFailed, this, _1),
+                               m_signingInfo,
+                               ndn::nfd::ROUTE_FLAG_CAPTURE);
 }
 
 void
 Nlsr::registerLocalhostPrefix()
 {
   m_nlsrFace.registerPrefix(LOCALHOST_PREFIX,
-                            std::bind(&Nlsr::onLocalhostRegistrationSuccess, this, _1),
+                            std::bind(&Nlsr::onRegistrationSuccess, this, _1),
                             std::bind(&Nlsr::registrationFailed, this, _1));
 }
 
 void
 Nlsr::onKeyInterest(const ndn::Name& name, const ndn::Interest& interest)
 {
+  NLSR_LOG_DEBUG("Got interest for certificate. Interest: " << interest.getName());
+
   const ndn::Name& interestName = interest.getName();
-  ndn::Name certName = interestName.getSubName(name.size());
+  const ndn::security::v2::Certificate* cert = getCertificate(interestName);
 
-  if (certName[-2].toUri() == "ID-CERT")
-    {
-      certName = certName.getPrefix(-1);
-    }
-  else if (certName[-1].toUri() != "ID-CERT")
-    {
-      NLSR_LOG_DEBUG("certName for interest " << interest << " is malformed,"
-                 << " contains incorrect namespace syntax");
-      return;
-    }
-
-  std::shared_ptr<const ndn::IdentityCertificate> cert = getCertificate(certName);
-
-  if (!static_cast<bool>(cert))
-    {
-      NLSR_LOG_DEBUG("cert is not found for " << interest);
+  if (cert == nullptr) {
+      NLSR_LOG_DEBUG("Certificate is not found for: " << interest);
       return; // cert is not found
-    }
+  }
 
-  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
-  data->setName(interestName);
-  data->setContent(cert->wireEncode());
-  m_keyChain.signWithSha256(*data);
-
-  m_nlsrFace.put(*data);
+  m_nlsrFace.put(*cert);
 }
 
 void
 Nlsr::onKeyPrefixRegSuccess(const ndn::Name& name)
 {
+  NLSR_LOG_DEBUG("KEY prefix: " << name << " registration is successful.");
 }
 
 void
@@ -432,7 +492,7 @@
     case ndn::nfd::FACE_EVENT_CREATED: {
       // Find the neighbor in our adjacency list
       auto adjacent = m_adjacencyList.findAdjacent(
-        ndn::util::FaceUri(faceEventNotification.getRemoteUri()));
+        ndn::FaceUri(faceEventNotification.getRemoteUri()));
       // If we have a neighbor by that FaceUri and it has no FaceId, we
       // have a match.
       if (adjacent != m_adjacencyList.end()) {
@@ -505,10 +565,11 @@
 Nlsr::registerAdjacencyPrefixes(const Adjacent& adj,
                                 const ndn::time::milliseconds& timeout)
 {
-  ndn::util::FaceUri faceUri = adj.getFaceUri();
+  ndn::FaceUri faceUri = adj.getFaceUri();
   double linkCost = adj.getLinkCost();
+  const ndn::Name& adjName = adj.getName();
 
-  m_fib.registerPrefix(adj.getName(), faceUri, linkCost,
+  m_fib.registerPrefix(adjName, faceUri, linkCost,
                        timeout, ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
 
   m_fib.registerPrefix(m_confParam.getChronosyncPrefix(),
@@ -518,12 +579,6 @@
   m_fib.registerPrefix(m_confParam.getLsaPrefix(),
                        faceUri, linkCost, timeout,
                        ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
-
-  ndn::Name broadcastKeyPrefix = DEFAULT_BROADCAST_PREFIX;
-  broadcastKeyPrefix.append("KEYS");
-  m_fib.registerPrefix(broadcastKeyPrefix,
-                       faceUri, linkCost, timeout,
-                       ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
 }
 
 void
@@ -553,8 +608,8 @@
 void
 Nlsr::scheduleDatasetFetch()
 {
-  NLSR_LOG_DEBUG("Scheduling Dataset Fetch in " << m_confParam.getFaceDatasetFetchInterval()
-             << " seconds");
+  NLSR_LOG_DEBUG("Scheduling Dataset Fetch in " << m_confParam.getFaceDatasetFetchInterval());
+
   m_scheduler.scheduleEvent(m_confParam.getFaceDatasetFetchInterval(),
     [this] {
       this->initializeFaces(
@@ -568,6 +623,35 @@
 }
 
 void
+Nlsr::enableIncomingFaceIdIndication()
+{
+  NLSR_LOG_DEBUG("Enabling incoming face id indication for local face.");
+
+  m_controller.start<ndn::nfd::FaceUpdateCommand>(
+    ndn::nfd::ControlParameters()
+      .setFlagBit(ndn::nfd::FaceFlagBit::BIT_LOCAL_FIELDS_ENABLED, true),
+    bind(&Nlsr::onFaceIdIndicationSuccess, this, _1),
+    bind(&Nlsr::onFaceIdIndicationFailure, this, _1));
+}
+
+void
+Nlsr::onFaceIdIndicationSuccess(const ndn::nfd::ControlParameters& cp)
+{
+  NLSR_LOG_DEBUG("Successfully enabled incoming face id indication"
+                 << "for face id " << cp.getFaceId());
+}
+
+void
+Nlsr::onFaceIdIndicationFailure(const ndn::nfd::ControlResponse& cr)
+{
+  std::ostringstream os;
+  os << "Failed to enable incoming face id indication feature: " <<
+        "(code: " << cr.getCode() << ", reason: " << cr.getText() << ")";
+
+  NLSR_LOG_DEBUG(os.str());
+}
+
+void
 Nlsr::startEventLoop()
 {
   m_nlsrFace.processEvents();
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index c3ed420..f16e918 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -29,7 +29,6 @@
 #include "lsdb.hpp"
 #include "name-prefix-list.hpp"
 #include "test-access-control.hpp"
-#include "validator.hpp"
 #include "publisher/lsdb-dataset-interest-handler.hpp"
 #include "route/fib.hpp"
 #include "route/name-prefix-table.hpp"
@@ -46,7 +45,10 @@
 
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/security/key-chain.hpp>
-#include <ndn-cxx/security/certificate-cache-ttl.hpp>
+#include <ndn-cxx/security/validator-config.hpp>
+#include <ndn-cxx/security/v2/certificate-fetcher-direct-fetch.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
+#include <ndn-cxx/security/signing-info.hpp>
 #include <ndn-cxx/util/scheduler.hpp>
 #include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
 #include <ndn-cxx/mgmt/nfd/face-monitor.hpp>
@@ -54,6 +56,9 @@
 #include <ndn-cxx/mgmt/nfd/face-status.hpp>
 #include <ndn-cxx/data.hpp>
 #include <ndn-cxx/encoding/block.hpp>
+#include <ndn-cxx/encoding/nfd-constants.hpp>
+#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
+#include <ndn-cxx/mgmt/nfd/control-response.hpp>
 
 namespace nlsr {
 
@@ -84,14 +89,19 @@
   onRegistrationSuccess(const ndn::Name& name);
 
   void
-  onLocalhostRegistrationSuccess(const ndn::Name& name);
-
-  void
   setInfoInterestFilter();
 
   void
   setLsaInterestFilter();
 
+  /*! \brief Add top level prefixes for Dispatcher
+   *
+   * All dispatcher-related sub-prefixes *must* be registered before sub-prefixes
+   * must be added before adding top
+   */
+  void
+  addDispatcherTopPrefix(const ndn::Name& topPrefix);
+
   void
   startEventLoop();
 
@@ -275,6 +285,13 @@
   registerAdjacencyPrefixes(const Adjacent& adj,
                             const ndn::time::milliseconds& timeout);
 
+  /*! \brief Add a certificate NLSR claims to be authoritative for to the certificate store.
+   *
+   * \sa CertificateStore
+   */
+  void
+  loadCertToPublish(const ndn::security::v2::Certificate& certificate);
+
   void
   initializeKey();
 
@@ -285,22 +302,12 @@
     m_validator.load(section, filename);
   }
 
-  Validator&
+  ndn::security::ValidatorConfig&
   getValidator()
   {
     return m_validator;
   }
 
-  /*! \brief Add a certificate NLSR claims to be authoritative for to the certificate store.
-   *
-   * \sa CertificateStore
-   */
-  void
-  loadCertToPublish(std::shared_ptr<ndn::IdentityCertificate> certificate)
-  {
-    m_certStore.insert(certificate);
-  }
-
   /*! \brief Find a certificate
    *
    * Find a certificate that NLSR has. First it checks against the
@@ -309,20 +316,16 @@
    * checks the cache of certficates it has already fetched. If none
    * can be found, it will return an empty pointer.
    */
-  std::shared_ptr<const ndn::IdentityCertificate>
-  getCertificate(const ndn::Name& certificateNameWithoutVersion)
+  const ndn::security::v2::Certificate*
+  getCertificate(const ndn::Name& certificateKeyName)
   {
-    shared_ptr<const ndn::IdentityCertificate> cert =
-      m_certStore.find(certificateNameWithoutVersion);
+    const ndn::security::v2::Certificate* cert =
+      m_certStore.find(certificateKeyName);
 
-    if (cert != nullptr) {
-      return cert;
-    }
-
-    return m_certificateCache->getCertificate(certificateNameWithoutVersion);
+    return cert;
   }
 
-  ndn::KeyChain&
+  ndn::security::v2::KeyChain&
   getKeyChain()
   {
     return m_keyChain;
@@ -334,6 +337,12 @@
     return m_defaultCertName;
   }
 
+  const ndn::security::SigningInfo&
+  getSigningInfo()
+  {
+    return m_signingInfo;
+  }
+
   update::PrefixUpdateProcessor&
   getPrefixUpdateProcessor()
   {
@@ -397,13 +406,6 @@
   }
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  void
-  addCertificateToCache(std::shared_ptr<ndn::IdentityCertificate> certificate)
-  {
-    if (certificate != nullptr) {
-      m_certificateCache->insertCertificate(certificate);
-    }
-  }
 
   security::CertificateStore&
   getCertificateStore()
@@ -457,13 +459,29 @@
   void
   scheduleDatasetFetch();
 
+  /*! \brief Enables NextHopFaceId indication in NFD for incoming data packet.
+   *
+   * After enabling, when NFD gets a data packet, it will put the incoming face id
+   * of the data in NextHopFaceId field of the packet. The NextHopFaceId will be used
+   * by DirectFetcher to fetch the certificates needed to validate the data packet.
+   * \sa https://redmine.named-data.net/projects/nfd/wiki/NDNLPv2#Consumer-Controlled-Forwarding
+   */
+  void
+  enableIncomingFaceIdIndication();
+
+  void
+  onFaceIdIndicationSuccess(const ndn::nfd::ControlParameters& cp);
+
+  void
+  onFaceIdIndicationFailure(const ndn::nfd::ControlResponse& cr);
+
 public:
   static const ndn::Name LOCALHOST_PREFIX;
 
 private:
   ndn::Face& m_nlsrFace;
   ndn::Scheduler& m_scheduler;
-  ndn::KeyChain& m_keyChain;
+  ndn::security::v2::KeyChain& m_keyChain;
   ConfParameter m_confParam;
   AdjacencyList m_adjacencyList;
   NamePrefixList m_namePrefixList;
@@ -486,20 +504,14 @@
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   HelloProtocol m_helloProtocol;
 
+  ndn::security::ValidatorConfig m_validator;
+
 private:
-  /*! \brief Where NLSR caches certificates it has fetched to validate
-   * Data signatures.
-   */
-  std::shared_ptr<ndn::CertificateCacheTtl> m_certificateCache;
   /*! \brief Where NLSR stores certificates it claims to be
    * authoritative for. Usually the router certificate.
    */
   security::CertificateStore m_certStore;
 
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  Validator m_validator;
-
-private:
   ndn::nfd::Controller m_controller;
   ndn::nfd::Controller m_faceDatasetController;
   ndn::security::SigningInfo m_signingInfo;
diff --git a/src/publisher/segment-publisher.hpp b/src/publisher/segment-publisher.hpp
index 59c44b4..2938980 100644
--- a/src/publisher/segment-publisher.hpp
+++ b/src/publisher/segment-publisher.hpp
@@ -40,9 +40,11 @@
 public:
   SegmentPublisher(FaceBase& face,
                    ndn::KeyChain& keyChain,
+                   const ndn::security::SigningInfo& signingInfo,
                    const ndn::time::milliseconds& freshnessPeriod = getDefaultFreshness())
     : m_face(face)
     , m_keyChain(keyChain)
+    , m_signingInfo(signingInfo)
     , m_freshnessPeriod(freshnessPeriod)
   {
   }
@@ -75,8 +77,7 @@
    * final block ID set to a timestamp.
    */
   void
-  publish(const ndn::Name& prefix,
-          const ndn::security::SigningInfo& signingInfo = ndn::security::KeyChain::DEFAULT_SIGNING_INFO)
+  publish(const ndn::Name& prefix)
   {
     ndn::EncodingBuffer buffer;
     generate(buffer);
@@ -107,7 +108,7 @@
         data->setFinalBlockId(segmentName[-1]);
       }
 
-      publishSegment(data, signingInfo);
+      publishSegment(data);
       ++segmentNo;
     } while (segmentBegin < end);
   }
@@ -122,15 +123,16 @@
   /*! \brief Helper function to sign and put data on a Face.
    */
   void
-  publishSegment(std::shared_ptr<ndn::Data>& data, const ndn::security::SigningInfo& signingInfo)
+  publishSegment(std::shared_ptr<ndn::Data>& data)
   {
-    m_keyChain.sign(*data, signingInfo);
+    m_keyChain.sign(*data, m_signingInfo);
     m_face.put(*data);
   }
 
 private:
   FaceBase& m_face;
   ndn::KeyChain& m_keyChain;
+  const ndn::security::SigningInfo& m_signingInfo;
   const ndn::time::milliseconds m_freshnessPeriod;
 };
 
diff --git a/src/route/fib.cpp b/src/route/fib.cpp
index d8a9909..c2ba20d 100644
--- a/src/route/fib.cpp
+++ b/src/route/fib.cpp
@@ -67,7 +67,7 @@
 
     if (isPrefixUpdatable(name)) {
       // Add nexthop to NDN-FIB
-      registerPrefix(name, ndn::util::FaceUri(it->getConnectingFaceUri()),
+      registerPrefix(name, ndn::FaceUri(it->getConnectingFaceUri()),
                      it->getRouteCostAsAdjustedInteger(),
                      ndn::time::seconds(m_refreshTime + GRACE_PERIOD),
                      ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
@@ -196,12 +196,12 @@
 }
 
 void
-Fib::registerPrefix(const ndn::Name& namePrefix, const ndn::util::FaceUri& faceUri,
+Fib::registerPrefix(const ndn::Name& namePrefix, const ndn::FaceUri& faceUri,
                     uint64_t faceCost,
                     const ndn::time::milliseconds& timeout,
                     uint64_t flags, uint8_t times)
 {
-  uint64_t faceId = m_adjacencyList.getFaceId(ndn::util::FaceUri(faceUri));
+  uint64_t faceId = m_adjacencyList.getFaceId(ndn::FaceUri(faceUri));
 
   if (faceId != 0) {
     ndn::nfd::ControlParameters faceParameters;
@@ -231,7 +231,7 @@
 
 void
 Fib::onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
-                           const std::string& message, const ndn::util::FaceUri& faceUri)
+                           const std::string& message, const ndn::FaceUri& faceUri)
 {
   NLSR_LOG_DEBUG(message << ": " << commandSuccessResult.getName() <<
              " Face Uri: " << faceUri << " faceId: " << commandSuccessResult.getFaceId());
@@ -250,7 +250,7 @@
 Fib::onRegistrationFailure(const ndn::nfd::ControlResponse& response,
                            const std::string& message,
                            const ndn::nfd::ControlParameters& parameters,
-                           const ndn::util::FaceUri& faceUri,
+                           const ndn::FaceUri& faceUri,
                            uint8_t times)
 {
   NLSR_LOG_DEBUG(message << ": " << response.getText() << " (code: " << response.getCode() << ")");
@@ -385,7 +385,7 @@
 
   for (const NextHop& hop : entry) {
     registerPrefix(entry.getName(),
-                   ndn::util::FaceUri(hop.getConnectingFaceUri()),
+                   ndn::FaceUri(hop.getConnectingFaceUri()),
                    hop.getRouteCostAsAdjustedInteger(),
                    ndn::time::seconds(m_refreshTime + GRACE_PERIOD),
                    ndn::nfd::ROUTE_FLAG_CAPTURE, 0);
diff --git a/src/route/fib.hpp b/src/route/fib.hpp
index 8cf7aa4..56b53a1 100644
--- a/src/route/fib.hpp
+++ b/src/route/fib.hpp
@@ -55,7 +55,7 @@
 {
 public:
   Fib(ndn::Face& face, ndn::Scheduler& scheduler, AdjacencyList& adjacencyList, ConfParameter& conf,
-      ndn::KeyChain& keyChain)
+      ndn::security::v2::KeyChain& keyChain)
     : m_scheduler(scheduler)
     , m_refreshTime(0)
     , m_controller(face, keyChain)
@@ -131,7 +131,7 @@
    */
   void
   registerPrefix(const ndn::Name& namePrefix,
-                 const ndn::util::FaceUri& faceUri,
+                 const ndn::FaceUri& faceUri,
                  uint64_t faceCost,
                  const ndn::time::milliseconds& timeout,
                  uint64_t flags,
@@ -173,7 +173,7 @@
    */
   void
   onRegistrationSuccess(const ndn::nfd::ControlParameters& commandSuccessResult,
-                        const std::string& message, const ndn::util::FaceUri& faceUri);
+                        const std::string& message, const ndn::FaceUri& faceUri);
 
   /*! \brief Retry a prefix (next-hop) registration up to three (3) times.
    */
@@ -181,7 +181,7 @@
   onRegistrationFailure(const ndn::nfd::ControlResponse& response,
                         const std::string& message,
                         const ndn::nfd::ControlParameters& parameters,
-                        const ndn::util::FaceUri& faceUri,
+                        const ndn::FaceUri& faceUri,
                         uint8_t times);
 
   /*! \brief Log a successful unregistration.
diff --git a/src/security/certificate-store.hpp b/src/security/certificate-store.hpp
index 4b84df6..0445318 100644
--- a/src/security/certificate-store.hpp
+++ b/src/security/certificate-store.hpp
@@ -26,7 +26,7 @@
 #include "../test-access-control.hpp"
 
 #include <ndn-cxx/interest.hpp>
-#include <ndn-cxx/security/v1/identity-certificate.hpp>
+#include <ndn-cxx/security/v2/certificate.hpp>
 
 namespace nlsr {
 namespace security {
@@ -42,21 +42,18 @@
 {
 public:
   void
-  insert(std::shared_ptr<ndn::IdentityCertificate> certificate)
+  insert(const ndn::security::v2::Certificate& certificate)
   {
-    if (certificate != nullptr) {
-      // Key is cert name without version
-      m_certificates[certificate->getName().getPrefix(-1)] = certificate;
-    }
+    m_certificates[certificate.getKeyName()] = certificate;
   }
 
-  std::shared_ptr<const ndn::IdentityCertificate>
-  find(const ndn::Name& certificateNameWithoutVersion) const
+  const ndn::security::v2::Certificate*
+  find(const ndn::Name keyName)
   {
-    CertMap::const_iterator it = m_certificates.find(certificateNameWithoutVersion);
+    CertMap::iterator it = m_certificates.find(keyName);
 
     if (it != m_certificates.end()) {
-      return it->second;
+      return &it->second;
     }
 
     return nullptr;
@@ -70,7 +67,7 @@
   }
 
 private:
-  typedef std::map<ndn::Name, std::shared_ptr<ndn::IdentityCertificate>> CertMap;
+  typedef std::map<ndn::Name, ndn::security::v2::Certificate> CertMap;
   CertMap m_certificates;
 };
 
diff --git a/src/tlv/coordinate-lsa.cpp b/src/tlv/coordinate-lsa.cpp
index 92809fe..02509a0 100644
--- a/src/tlv/coordinate-lsa.cpp
+++ b/src/tlv/coordinate-lsa.cpp
@@ -21,10 +21,12 @@
 
 #include "coordinate-lsa.hpp"
 #include "tlv-nlsr.hpp"
+#include "logger.hpp"
 
 #include <ndn-cxx/util/concepts.hpp>
 #include <ndn-cxx/encoding/block-helpers.hpp>
-#include "logger.hpp"
+
+#include <iostream>
 
 namespace nlsr {
 namespace tlv {
diff --git a/src/update/manager-base.cpp b/src/update/manager-base.cpp
index 5a1034c..a93aaba 100644
--- a/src/update/manager-base.cpp
+++ b/src/update/manager-base.cpp
@@ -55,7 +55,7 @@
                                              const ndn::Interest& interest,
                                              const ndn::mgmt::ControlParameters& parameters,
                                              const ndn::mgmt::CommandContinuation& done)
-    {
+{
   const ndn::nfd::ControlParameters& castParams =
     static_cast<const ndn::nfd::ControlParameters&>(parameters);
 
diff --git a/src/update/manager-base.hpp b/src/update/manager-base.hpp
index 33df589..0dddbd6 100644
--- a/src/update/manager-base.hpp
+++ b/src/update/manager-base.hpp
@@ -103,9 +103,9 @@
 {
 public:
   CommandManagerBase(ndn::mgmt::Dispatcher& m_dispatcher,
-                      NamePrefixList& m_namePrefixList,
-                      Lsdb& lsdb,
-                      const std::string& module);
+                     NamePrefixList& m_namePrefixList,
+                     Lsdb& lsdb,
+                     const std::string& module);
 
   /*! \brief add desired name prefix to the advertised name prefix list
    *         or insert a prefix into the FIB if parameters is valid.
diff --git a/src/update/prefix-update-processor.cpp b/src/update/prefix-update-processor.cpp
index 4ad75dd..478380f 100644
--- a/src/update/prefix-update-processor.cpp
+++ b/src/update/prefix-update-processor.cpp
@@ -24,7 +24,7 @@
 #include "nlsr.hpp"
 #include <ndn-cxx/mgmt/nfd/control-response.hpp>
 #include <ndn-cxx/tag.hpp>
-#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/face.hpp>
 
 namespace nlsr {
 namespace update {
@@ -52,13 +52,10 @@
 PrefixUpdateProcessor::PrefixUpdateProcessor(ndn::mgmt::Dispatcher& dispatcher,
                                              ndn::Face& face,
                                              NamePrefixList& namePrefixList,
-                                             Lsdb& lsdb,
-                                             const ndn::Name broadcastPrefix,
-                                             ndn::KeyChain& keyChain,
-                                             std::shared_ptr<ndn::CertificateCacheTtl> certificateCache,
-                                             security::CertificateStore& certStore)
+                                             Lsdb& lsdb)
   : CommandManagerBase(dispatcher, namePrefixList, lsdb, "prefix-update")
-  , m_validator(face, broadcastPrefix, certificateCache, certStore)
+
+  , m_validator(ndn::make_unique<ndn::security::v2::CertificateFetcherDirectFetch>(face))
 {
   NLSR_LOG_DEBUG("Setting dispatcher to capture Interests for: "
     << ndn::Name(Nlsr::LOCALHOST_PREFIX).append("prefix-update"));
@@ -84,17 +81,16 @@
               const ndn::mgmt::AcceptContinuation& accept,
               const ndn::mgmt::RejectContinuation& reject) {
     m_validator.validate(interest,
-      [accept] (const std::shared_ptr<const ndn::Interest>& request) {
+      [accept] (const ndn::Interest& request) {
 
-        auto signer1 = getSignerFromTag(*request);
+        auto signer1 = getSignerFromTag(request);
         std::string signer = signer1.value_or("*");
-        NLSR_LOG_DEBUG("accept " << request->getName() << " signer=" << signer);
+        NLSR_LOG_DEBUG("accept " << request.getName() << " signer=" << signer);
         accept(signer);
       },
-      [reject] (const std::shared_ptr<const ndn::Interest>& request,
-                const std::string& failureInfo) {
-        NLSR_LOG_DEBUG("reject " << request->getName() << " signer=" <<
-                      getSignerFromTag(*request).value_or("?") << ' ' << failureInfo);
+      [reject] (const ndn::Interest& request, const ndn::security::v2::ValidationError& error) {
+        NLSR_LOG_DEBUG("reject " << request.getName() << " signer=" <<
+                        getSignerFromTag(request).value_or("?") << ' ' << error);
         reject(ndn::mgmt::RejectReply::STATUS403);
       });
   };
diff --git a/src/update/prefix-update-processor.hpp b/src/update/prefix-update-processor.hpp
index 52780e6..a602497 100644
--- a/src/update/prefix-update-processor.hpp
+++ b/src/update/prefix-update-processor.hpp
@@ -25,11 +25,11 @@
 #include "manager-base.hpp"
 #include "prefix-update-commands.hpp"
 #include "test-access-control.hpp"
-#include "validator.hpp"
 
-#include <ndn-cxx/security/certificate-cache-ttl.hpp>
+#include <ndn-cxx/util/io.hpp>
 #include <ndn-cxx/security/key-chain.hpp>
-#include <ndn-cxx/security/v2/validator.hpp>
+#include <ndn-cxx/security/v2/certificate-storage.hpp>
+#include <ndn-cxx/util/io.hpp>
 
 #include <boost/property_tree/ptree.hpp>
 #include <memory>
@@ -50,11 +50,7 @@
   PrefixUpdateProcessor(ndn::mgmt::Dispatcher& dispatcher,
                         ndn::Face& face,
                         NamePrefixList& namePrefixList,
-                        Lsdb& lsdb,
-                        const ndn::Name broadcastPrefix,
-                        ndn::KeyChain& keyChain,
-                        std::shared_ptr<ndn::CertificateCacheTtl> certificateCache,
-                        security::CertificateStore& certStore);
+                        Lsdb& lsdb);
 
   /*! \brief Load the validator's configuration from a section of a
    * configuration file.
@@ -70,8 +66,7 @@
   void
   loadValidator(ConfigSection section, const std::string& filename);
 
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  Validator&
+  ndn::security::ValidatorConfig&
   getValidator()
   {
     return m_validator;
@@ -88,7 +83,7 @@
   makeAuthorization();
 
 private:
-  Validator m_validator;
+  ndn::security::ValidatorConfig m_validator;
 };
 
 } // namespace update
diff --git a/src/validator.cpp b/src/validator.cpp
deleted file mode 100644
index a73c9ee..0000000
--- a/src/validator.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  The University of Memphis,
- *                           Regents of the University of California
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#include "validator.hpp"
-
-namespace nlsr {
-
-void
-Validator::checkPolicy(const ndn::Data& data, int nSteps, const ndn::OnDataValidated& onValidated,
-                       const ndn::OnDataValidationFailed& onValidationFailed,
-                       std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps)
-{
-  if (!m_shouldValidate) {
-    onValidated(data.shared_from_this());
-  }
-  else {
-    ValidatorConfig::checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
-  }
-}
-
-void
-Validator::afterCheckPolicy(const NextSteps& nextSteps, const OnFailure& onFailure)
-{
-  if (m_face == nullptr) {
-    onFailure("Require more information to validate the packet!");
-    return;
-  }
-
-  for (const std::shared_ptr<ndn::ValidationRequest>& request : nextSteps) {
-
-    ndn::Interest& interest = request->m_interest;
-
-    // Look for certificate in permanent storage
-    std::shared_ptr<const ndn::IdentityCertificate> cert = m_certStore.find(interest.getName());
-
-    if (cert != nullptr) {
-      // If the certificate is found, no reason to express interest
-      std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(interest.getName());
-      data->setContent(cert->wireEncode());
-
-      Validator::onData(interest, *data, request);
-    }
-    else {
-      // Prepend broadcast prefix to interest name
-      ndn::Name broadcastName = m_broadcastPrefix;
-      broadcastName.append(interest.getName());
-      interest.setName(broadcastName);
-
-      // Attempt to fetch the certificate
-      m_face->expressInterest(interest,
-                              std::bind(&Validator::onData, this, _1, _2, request),
-                              std::bind(&Validator::onTimeout, // Nack
-                                        this, _1, request->m_nRetries,
-                                        onFailure,
-                                        request),
-                              std::bind(&Validator::onTimeout,
-                                        this, _1, request->m_nRetries,
-                                        onFailure,
-                                        request));
-    }
-  }
-}
-
-std::shared_ptr<const ndn::Data>
-Validator::preCertificateValidation(const ndn::Data& data)
-{
-  std::shared_ptr<ndn::Data> internalData = std::make_shared<ndn::Data>();
-  internalData->wireDecode(data.getContent().blockFromValue());
-  return internalData;
-}
-
-} // namespace nlsr
diff --git a/src/validator.hpp b/src/validator.hpp
deleted file mode 100644
index c4f2a19..0000000
--- a/src/validator.hpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  The University of Memphis,
- *                           Regents of the University of California,
- *                           Arizona Board of Regents.
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#ifndef NLSR_VALIDATOR_HPP
-#define NLSR_VALIDATOR_HPP
-
-#include "common.hpp"
-#include "security/certificate-store.hpp"
-
-#include <ndn-cxx/security/validator-config.hpp>
-
-namespace nlsr {
-
-class Validator : public ndn::ValidatorConfig
-{
-public:
-  class Error : public ndn::ValidatorConfig::Error
-  {
-  public:
-    explicit
-    Error(const std::string& what)
-      : ndn::ValidatorConfig::Error(what)
-    {
-    }
-  };
-
-  explicit
-  Validator(ndn::Face& face,
-            const ndn::Name broadcastPrefix,
-            const std::shared_ptr<ndn::CertificateCache>& cache,
-            security::CertificateStore& certStore,
-            const int stepLimit = 10)
-    : ndn::ValidatorConfig(face, cache, ndn::ValidatorConfig::DEFAULT_GRACE_INTERVAL, stepLimit)
-    , m_shouldValidate(true)
-    , m_broadcastPrefix(broadcastPrefix)
-    , m_certStore(certStore)
-  {
-    m_broadcastPrefix.append("KEYS");
-  }
-
-  virtual
-  ~Validator()
-  {
-  }
-
-  const ndn::Name&
-  getBroadcastPrefix()
-  {
-    return m_broadcastPrefix;
-  }
-
-  void
-  setBroadcastPrefix(const ndn::Name& broadcastPrefix)
-  {
-    m_broadcastPrefix = broadcastPrefix;
-  }
-
-protected:
-  typedef std::vector<std::shared_ptr<ndn::ValidationRequest>> NextSteps;
-
-  void
-  checkPolicy(const ndn::Data& data,
-              int nSteps,
-              const ndn::OnDataValidated& onValidated,
-              const ndn::OnDataValidationFailed& onValidationFailed,
-              std::vector<shared_ptr<ndn::ValidationRequest>>& nextSteps) override;
-
-  void
-  afterCheckPolicy(const NextSteps& nextSteps,
-                   const OnFailure& onFailure) override;
-
-  std::shared_ptr<const ndn::Data>
-  preCertificateValidation(const ndn::Data& data) override;
-
-PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  bool m_shouldValidate;
-
-private:
-  ndn::Name m_broadcastPrefix;
-  security::CertificateStore& m_certStore;
-};
-
-} // namespace nlsr
-
-#endif // NLSR_VALIDATOR_HPP
diff --git a/tests-integrated/boost-test.hpp b/tests-integrated/boost-test.hpp
deleted file mode 100644
index 91f1604..0000000
--- a/tests-integrated/boost-test.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  The University of Memphis
- *                           Regents of the University of California,
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-
-#ifndef NLSR_TESTS_INTEGRATED_BOOST_TEST_HPP
-#define NLSR_TESTS_INTEGRATED_BOOST_TEST_HPP
-
-// suppress warnings from Boost.Test
-#pragma GCC system_header
-#pragma clang system_header
-
-#include <boost/test/unit_test.hpp>
-#include <boost/concept_check.hpp>
-#include <boost/test/output_test_stream.hpp>
-
-#endif // NLSR_TESTS_INTEGRATED_BOOST_TEST_HPP
diff --git a/tests-integrated/main.cpp b/tests-integrated/main.cpp
deleted file mode 100644
index a2e4e92..0000000
--- a/tests-integrated/main.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  The University of Memphis,
- *                           Regents of the University of California
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#define BOOST_TEST_MAIN 1
-#define BOOST_TEST_DYN_LINK 1
-
-#include "boost-test.hpp"
diff --git a/tests-integrated/test-validator.cpp b/tests-integrated/test-validator.cpp
deleted file mode 100644
index 406ef0c..0000000
--- a/tests-integrated/test-validator.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  The University of Memphis,
- *                           Regents of the University of California,
- *                           Arizona Board of Regents.
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
-
-#include "validator.hpp"
-
-#include <ndn-cxx/security/certificate-cache-ttl.hpp>
-#include <ndn-cxx/security/key-chain.hpp>
-#include <ndn-cxx/util/scheduler.hpp>
-
-#include "boost-test.hpp"
-#include "common.hpp"
-#include "security/certificate-store.hpp"
-
-namespace nlsr {
-
-namespace test {
-
-BOOST_AUTO_TEST_SUITE(TestValidator)
-
-struct ValidatorFixture
-{
-  ValidatorFixture()
-    : m_face2(m_face.getIoService())
-    , m_scheduler(m_face.getIoService())
-    , m_keyPrefix("/ndn/broadcast/KEYS")
-    , m_certificateCache(new ndn::CertificateCacheTtl(m_face.getIoService()))
-    , m_validator(m_face2, ndn::Name("/ndn/broadcast"), m_certificateCache, m_certStore)
-    , m_identity("/TestValidator/NLSR")
-    , m_wasValidated(false)
-  {
-    m_face.setInterestFilter(m_keyPrefix,
-                             std::bind(&ValidatorFixture::onKeyInterest, this, _1, _2),
-                             std::bind(&ValidatorFixture::onKeyPrefixRegSuccess, this, _1),
-                             std::bind(&ValidatorFixture::registrationFailed, this, _1, _2));
-
-    m_keyChain.createIdentity(m_identity);
-    ndn::Name certName = m_keyChain.getDefaultCertificateNameForIdentity(m_identity);
-    m_cert = m_keyChain.getCertificate(certName);
-    ndn::io::save(*m_cert, "trust-anchor.cert");
-
-    const std::string CONFIG =
-      "rule\n"
-      "{\n"
-      "  id \"NSLR Hello Rule\"\n"
-      "  for data\n"
-      "  filter\n"
-      "  {\n"
-      "    type name\n"
-      "    regex ^[^<NLSR><INFO>]*<NLSR><INFO><><>$\n"
-      "  }\n"
-      "  checker\n"
-      "  {\n"
-      "    type customized\n"
-      "    sig-type rsa-sha256\n"
-      "    key-locator\n"
-      "    {\n"
-      "      type name\n"
-      "      hyper-relation\n"
-      "      {\n"
-      "        k-regex ^([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><ID-CERT>$\n"
-      "        k-expand \\\\1\n"
-      "        h-relation equal\n"
-      "        p-regex ^([^<NLSR><INFO>]*)<NLSR><INFO><><>$\n"
-      "        p-expand \\\\1\n"
-      "      }\n"
-      "    }\n"
-      "  }\n"
-      "}\n"
-      "rule\n"
-      "{\n"
-      "  id \"Single Rule\"\n"
-      "  for data\n"
-      "  filter\n"
-      "  {\n"
-      "    type name\n"
-      "    regex ^<TestValidator>([^<KEY><NLSR>]*)<NLSR><KEY><ksk-.*><><>$\n"
-      "  }\n"
-      "  checker\n"
-      "  {\n"
-      "    type fixed-signer\n"
-      "    sig-type rsa-sha256\n"
-      "    signer\n"
-      "    {\n"
-      "      type file\n"
-      "      file-name \"trust-anchor.cert\"\n"
-      "    }\n"
-      "  }\n"
-      "}\n";
-
-    const boost::filesystem::path CONFIG_PATH =
-      (boost::filesystem::current_path() / std::string("unit-test.conf"));
-
-    m_validator.load(CONFIG, CONFIG_PATH.native());
-  }
-
-  ~ValidatorFixture()
-  {
-    m_keyChain.deleteIdentity(m_identity);
-
-    const boost::filesystem::path CERT_PATH =
-      (boost::filesystem::current_path() / std::string("trust-anchor.cert"));
-    boost::filesystem::remove(CERT_PATH);
-  }
-
-  void
-  onKeyInterest(const ndn::Name& name, const ndn::Interest& interest)
-  {
-    const ndn::Name& interestName = interest.getName();
-
-    ndn::Name certName = interestName.getSubName(name.size());
-
-    if (certName[-2].toUri() == "ID-CERT")
-      {
-        certName = certName.getPrefix(-1);
-      }
-    else if (certName[-1].toUri() != "ID-CERT")
-      return; //Wrong key interest.
-
-    if (certName != m_cert->getName().getPrefix(-1))
-      return; //No such a cert
-
-    std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(interestName);
-    data->setContent(m_cert->wireEncode());
-    m_keyChain.signWithSha256(*data);
-
-    m_face.put(*data);
-  }
-
-  void
-  onKeyPrefixRegSuccess(const ndn::Name& name)
-  {
-    BOOST_REQUIRE(true);
-  }
-
-  void
-  registrationFailed(const ndn::Name& name, const std::string& msg)
-  {
-    std::cerr << "Failure Info: " << msg << std::endl;
-    BOOST_REQUIRE(false);
-  }
-
-  void
-  onValidated(const std::shared_ptr<const ndn::Data>& data)
-  {
-    m_wasValidated = true;
-  }
-
-  void
-  onValidationFailed(const std::shared_ptr<const ndn::Data>& data,
-                     const std::string& failureInfo)
-  {
-    std::cerr << "Failure Info: " << failureInfo << std::endl;
-    m_wasValidated = false;
-  }
-
-  void
-  validate(const std::shared_ptr<const ndn::Data>& data)
-  {
-    m_validator.validate(*data,
-                         std::bind(&ValidatorFixture::onValidated, this, _1),
-                         std::bind(&ValidatorFixture::onValidationFailed, this, _1, _2));
-  }
-
-  void
-  terminate()
-  {
-    m_face.getIoService().stop();
-  }
-
-protected:
-  ndn::Face m_face;
-  ndn::Face m_face2;
-  ndn::Scheduler m_scheduler;
-  const ndn::Name m_keyPrefix;
-  std::shared_ptr<ndn::CertificateCacheTtl> m_certificateCache;
-  security::CertificateStore m_certStore;
-  nlsr::Validator m_validator;
-
-  ndn::KeyChain m_keyChain;
-  ndn::Name m_identity;
-  std::shared_ptr<ndn::IdentityCertificate> m_cert;
-
-  bool m_wasValidated;
-};
-
-BOOST_FIXTURE_TEST_CASE(InfoCertFetch, ValidatorFixture)
-{
-  ndn::Name dataName = m_identity;
-  dataName.append("INFO").append("neighbor").append("version");
-  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(dataName);
-  m_keyChain.signByIdentity(*data, m_identity);
-
-  m_scheduler.scheduleEvent(ndn::time::milliseconds(200),
-                            std::bind(&ValidatorFixture::validate, this, data));
-  m_scheduler.scheduleEvent(ndn::time::milliseconds(1000),
-                            std::bind(&ValidatorFixture::terminate, this));
-  BOOST_REQUIRE_NO_THROW(m_face.processEvents());
-
-  BOOST_CHECK(m_wasValidated);
-}
-
-BOOST_FIXTURE_TEST_CASE(CertificateStorage, ValidatorFixture)
-{
-  std::vector<ndn::security::v1::CertificateSubjectDescription> subjectDescription;
-
-  // Create an operator identity
-  ndn::Name opIdentity("/TestValidator/operator/NLSR");
-  m_keyChain.createIdentity(opIdentity);
-
-  // Create an operator cert signed by the trust anchor
-  ndn::Name keyName = m_keyChain.generateRsaKeyPairAsDefault(opIdentity, true);
-  std::shared_ptr<ndn::IdentityCertificate> opCert =
-    m_keyChain.prepareUnsignedIdentityCertificate(keyName,
-                                                  m_identity,
-                                                  ndn::time::system_clock::now(),
-                                                  ndn::time::system_clock::now()
-                                                    + ndn::time::days(1),
-                                                  subjectDescription);
-  m_keyChain.signByIdentity(*opCert, m_identity);
-  m_keyChain.addCertificateAsIdentityDefault(*opCert);
-
-  // Sign data with operator cert
-  ndn::Name dataName = opIdentity;
-  dataName.append("INFO").append("neighbor").append("version");
-  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(dataName);
-  m_keyChain.signByIdentity(*data, opIdentity);
-
-  // Check without cert in CertificateStore
-  m_scheduler.scheduleEvent(ndn::time::milliseconds(200),
-                            std::bind(&ValidatorFixture::validate, this, data));
-  m_scheduler.scheduleEvent(ndn::time::milliseconds(1000),
-                            std::bind(&ValidatorFixture::terminate, this));
-
-  BOOST_REQUIRE_NO_THROW(m_face.processEvents());
-  BOOST_CHECK_EQUAL(m_wasValidated, false);
-
-  // Check with cert in CertificateStore
-  m_certStore.insert(opCert);
-
-  m_scheduler.scheduleEvent(ndn::time::milliseconds(200),
-                            std::bind(&ValidatorFixture::validate, this, data));
-  m_scheduler.scheduleEvent(ndn::time::milliseconds(1000),
-                            std::bind(&ValidatorFixture::terminate, this));
-
-  BOOST_REQUIRE_NO_THROW(m_face.processEvents());
-  BOOST_CHECK(m_wasValidated);
-
-  // Cleanup
-  m_keyChain.deleteIdentity(opIdentity);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace test
-} // namespace nlsr
diff --git a/tests-integrated/wscript b/tests-integrated/wscript
deleted file mode 100644
index ce1ee26..0000000
--- a/tests-integrated/wscript
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-
-"""
-Copyright (c) 2014-2016,  The University of Memphis
-                          Regents of the University of California,
-
-This file is part of NLSR (Named-data Link State Routing).
-See AUTHORS.md for complete list of NLSR authors and contributors.
-
-NLSR is free software: you can redistribute it and/or modify it under the terms
-of the GNU General Public License as published by the Free Software Foundation,
-either version 3 of the License, or (at your option) any later version.
-
-NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-PURPOSE.  See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
-"""
-
-top = '..'
-
-def build(bld):
-    if bld.env['WITH_TESTS']:
-        integrated_test_main = bld(
-            target='integrated-tests-main',
-            name='integrated-tests-main',
-            features='cxx',
-            source=bld.path.ant_glob(['*.cpp']),
-            use='nlsr-objects',
-          )
-
-        integrated_test_nlsr = bld.program (
-            target="../integrated-tests-nlsr",
-            features="cxx cxxprogram",
-            source=bld.path.ant_glob(['nlsr/**/*.cpp']),
-            use='nlsr-objects integrated-tests-main',
-            includes='.',
-            install_path=None,
-            )
diff --git a/tests/boost-multi-log-formatter.hpp b/tests/boost-multi-log-formatter.hpp
new file mode 100644
index 0000000..519e7da
--- /dev/null
+++ b/tests/boost-multi-log-formatter.hpp
@@ -0,0 +1,214 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017 Regents of the University of California.
+ *
+ * Based on work by Martin Ba (http://stackoverflow.com/a/26718189)
+ *
+ * This file is distributed under the Boost Software License, Version 1.0.
+ * (See http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef NDN_TESTS_BOOST_MULTI_LOG_FORMATTER_HPP
+#define NDN_TESTS_BOOST_MULTI_LOG_FORMATTER_HPP
+
+#include <boost/version.hpp>
+
+#if BOOST_VERSION >= 105900
+#include <boost/test/unit_test_parameters.hpp>
+#else
+#include <boost/test/detail/unit_test_parameters.hpp>
+#endif // BOOST_VERSION >= 105900
+
+#include <boost/test/unit_test_log_formatter.hpp>
+#include <boost/test/output/compiler_log_formatter.hpp>
+#include <boost/test/output/xml_log_formatter.hpp>
+
+namespace boost {
+namespace unit_test {
+namespace output {
+
+/**
+ * @brief Log formatter for Boost.Test that outputs the logging to multiple formatters
+ *
+ * The log formatter is designed to output to one or multiple formatters at the same time.  For
+ * example, one HRF formatter can output to the standard output, while XML formatter output to
+ * the file.
+ *
+ * Usage:
+ *
+ *     // Call in init_unit_test_suite: (this will override the --log_format parameter)
+ *     auto formatter = new boost::unit_test::output::multi_log_formatter; // same as already configured logger
+ *
+ *     // Prepare and add additional logger(s)
+ *     formatter.add(std::make_shared<boost::unit_test::output::xml_log_formatter>(),
+ *                   std::make_shared<std::ofstream>("out.xml"));
+ *
+ *      boost::unit_test::unit_test_log.set_formatter(formatter);
+ *
+ * @note Calling `boost::unit_test::unit_test_log.set_stream(...)` will change the stream for
+ *       the original logger.
+ */
+class multi_log_formatter : public unit_test_log_formatter
+{
+public:
+  /**
+   * @brief Create instance of the logger, based on the configured logger instance
+   */
+  multi_log_formatter()
+  {
+    auto format =
+#if BOOST_VERSION > 105900
+      runtime_config::get<output_format>(runtime_config::LOG_FORMAT);
+#else
+      runtime_config::log_format();
+#endif // BOOST_VERSION > 105900
+
+    switch (format) {
+      default:
+#if BOOST_VERSION >= 105900
+      case OF_CLF:
+#else
+      case CLF:
+#endif // BOOST_VERSION >= 105900
+        m_loggers.push_back({std::make_shared<compiler_log_formatter>(), nullptr});
+        break;
+#if BOOST_VERSION >= 105900
+      case OF_XML:
+#else
+      case XML:
+#endif // BOOST_VERSION >= 105900
+        m_loggers.push_back({std::make_shared<xml_log_formatter>(), nullptr});
+        break;
+    }
+  }
+
+  void
+  add(std::shared_ptr<unit_test_log_formatter> formatter, std::shared_ptr<std::ostream> os)
+  {
+    m_loggers.push_back({formatter, os});
+  }
+
+  // Formatter interface
+  void
+  log_start(std::ostream& os, counter_t test_cases_amount)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_start(l.os == nullptr ? os : *l.os, test_cases_amount);
+  }
+
+  void
+  log_finish(std::ostream& os)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_finish(l.os == nullptr ? os : *l.os);
+  }
+
+  void
+  log_build_info(std::ostream& os)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_build_info(l.os == nullptr ? os : *l.os);
+  }
+
+  void
+  test_unit_start(std::ostream& os, const test_unit& tu)
+  {
+    for (auto& l : m_loggers)
+      l.logger->test_unit_start(l.os == nullptr ? os : *l.os, tu);
+  }
+
+  void
+  test_unit_finish(std::ostream& os, const test_unit& tu, unsigned long elapsed)
+  {
+    for (auto& l : m_loggers)
+      l.logger->test_unit_finish(l.os == nullptr ? os : *l.os, tu, elapsed);
+  }
+
+  void
+  test_unit_skipped(std::ostream& os, const test_unit& tu)
+  {
+    for (auto& l : m_loggers)
+      l.logger->test_unit_skipped(l.os == nullptr ? os : *l.os, tu);
+  }
+
+#if BOOST_VERSION >= 105900
+  void
+  log_exception_start(std::ostream& os, const log_checkpoint_data& lcd, const execution_exception& ex)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_exception_start(l.os == nullptr ? os : *l.os, lcd, ex);
+  }
+
+  void
+  log_exception_finish(std::ostream& os)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_exception_finish(l.os == nullptr ? os : *l.os);
+  }
+#else
+  void
+  log_exception(std::ostream& os, const log_checkpoint_data& lcd, const execution_exception& ex)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_exception(l.os == nullptr ? os : *l.os, lcd, ex);
+  }
+#endif // BOOST_VERSION >= 105900
+
+  void
+  log_entry_start(std::ostream& os, const log_entry_data& entry_data, log_entry_types let)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_entry_start(l.os == nullptr ? os : *l.os, entry_data, let);
+  }
+
+  void
+  log_entry_value(std::ostream& os, const_string value)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_entry_value(l.os == nullptr ? os : *l.os, value);
+  }
+
+  void
+  log_entry_finish(std::ostream& os)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_entry_finish(l.os == nullptr ? os : *l.os);
+  }
+
+#if BOOST_VERSION >= 105900
+  void
+  entry_context_start(std::ostream& os, log_level level)
+  {
+    for (auto& l : m_loggers)
+      l.logger->entry_context_start(l.os == nullptr ? os : *l.os, level);
+  }
+
+  void
+  log_entry_context(std::ostream& os, const_string value)
+  {
+    for (auto& l : m_loggers)
+      l.logger->log_entry_context(l.os == nullptr ? os : *l.os, value);
+  }
+
+  void
+  entry_context_finish(std::ostream& os)
+  {
+    for (auto& l : m_loggers)
+      l.logger->entry_context_finish(l.os == nullptr ? os : *l.os);
+  }
+#endif // BOOST_VERSION >= 105900
+
+private:
+  struct LoggerInfo
+  {
+    std::shared_ptr<unit_test_log_formatter> logger;
+    std::shared_ptr<std::ostream> os;
+  };
+  std::vector<LoggerInfo> m_loggers;
+};
+
+} // namespace output
+} // namespace unit_test
+} // namespace boost
+
+#endif // NDN_TESTS_BOOST_MULTI_LOG_FORMATTER_HPP
diff --git a/tests/identity-fixture.cpp b/tests/identity-fixture.cpp
deleted file mode 100644
index b2910ed..0000000
--- a/tests/identity-fixture.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  The University of Memphis,
- *                           Regents of the University of California
- *
- * This file is part of NLSR (Named-data Link State Routing).
- * See AUTHORS.md for complete list of NLSR authors and contributors.
- *
- * NLSR is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- **/
- /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#include <ndn-cxx/security/key-chain.hpp>
-
-#include "boost-test.hpp"
-
-namespace nlsr {
-
-// OSX KeyChain, when used on a headless server,
-// forbids usage of a private key if that key isn't created by the calling process.
-// Therefore, unit testing must create its own key pair.
-
-class IdentityFixture
-{
-public:
-  IdentityFixture()
-  {
-    // save the old default identity
-    try {
-      m_oldDefaultIdentity = m_keyChain.getDefaultIdentity();
-      m_hasOldDefaultIdentity = true;
-    }
-    catch (ndn::SecPublicInfo::Error& e) {
-      m_hasOldDefaultIdentity = false;
-    }
-
-    m_newIdentity = "/nlsr-test-identity";
-    m_newIdentity.appendVersion();
-
-    // create the new identity and self-signed certificate
-    m_keyChain.createIdentity(m_newIdentity);
-
-    // set the new identity as default identity,
-    // and the corresponding certificate becomes the default certificate
-    m_keyChain.setDefaultIdentity(m_newIdentity);
-  }
-
-  ~IdentityFixture()
-  {
-    // recover the old default setting
-    if (m_hasOldDefaultIdentity) {
-      m_keyChain.setDefaultIdentity(m_oldDefaultIdentity);
-    }
-
-    // remove the temporarily created identity and certificates
-    // XXX This has no effect if oldDefaultIdentity doesn't exist.
-    //     newIdentity would be kept as default.
-    m_keyChain.deleteIdentity(m_newIdentity);
-  }
-
-private:
-  ndn::KeyChain m_keyChain;
-  bool m_hasOldDefaultIdentity;
-  ndn::Name m_oldDefaultIdentity;
-  ndn::Name m_newIdentity;
-};
-
-BOOST_GLOBAL_FIXTURE(IdentityFixture)
-#if BOOST_VERSION >= 105900
-;
-#endif // BOOST_VERSION >= 105900
-
-} // namespace nlsr
diff --git a/tests/identity-management-fixture.cpp b/tests/identity-management-fixture.cpp
new file mode 100644
index 0000000..c5aed73
--- /dev/null
+++ b/tests/identity-management-fixture.cpp
@@ -0,0 +1,143 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "identity-management-fixture.hpp"
+
+#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/security/v2/additional-description.hpp>
+
+#include <boost/filesystem.hpp>
+
+namespace nlsr {
+namespace tests {
+
+namespace v2 = ndn::security::v2;
+namespace io = ndn::io;
+namespace time = ndn::time;
+
+IdentityManagementBaseFixture::~IdentityManagementBaseFixture()
+{
+  boost::system::error_code ec;
+  for (const auto& certFile : m_certFiles) {
+    boost::filesystem::remove(certFile, ec); // ignore error
+  }
+}
+
+bool
+IdentityManagementBaseFixture::saveCertToFile(const ndn::Data& obj,
+                                              const std::string& filename)
+{
+  m_certFiles.insert(filename);
+  try {
+    io::save(obj, filename);
+    return true;
+  }
+  catch (const io::Error&) {
+    return false;
+  }
+}
+
+IdentityManagementFixture::IdentityManagementFixture()
+  : m_keyChain("pib-memory:", "tpm-memory:")
+{
+}
+
+ndn::security::Identity
+IdentityManagementFixture::addIdentity(const ndn::Name& identityName,
+                                       const ndn::KeyParams& params)
+{
+  auto identity = m_keyChain.createIdentity(identityName, params);
+  m_identities.insert(identityName);
+  return identity;
+}
+
+bool
+IdentityManagementFixture::saveCertificate(const ndn::security::Identity& identity,
+                                           const std::string& filename)
+{
+  try {
+    auto cert = identity.getDefaultKey().getDefaultCertificate();
+    return saveCertToFile(cert, filename);
+  }
+  catch (const ndn::security::Pib::Error&) {
+    return false;
+  }
+}
+
+ndn::security::Identity
+IdentityManagementFixture::addSubCertificate(const ndn::Name& subIdentityName,
+                                             const ndn::security::Identity& issuer,
+                                             const ndn::KeyParams& params)
+{
+  auto subIdentity = addIdentity(subIdentityName, params);
+
+  v2::Certificate request = subIdentity.getDefaultKey().getDefaultCertificate();
+
+  request.setName(request.getKeyName().append("parent").appendVersion());
+
+  ndn::SignatureInfo info;
+  info.setValidityPeriod(ndn::security::ValidityPeriod(time::system_clock::now(),
+                                                       time::system_clock::now()
+                                                       + time::days(7300)));
+
+  v2::AdditionalDescription description;
+  description.set("type", "sub-certificate");
+  info.appendTypeSpecificTlv(description.wireEncode());
+
+  m_keyChain.sign(request, ndn::signingByIdentity(issuer).setSignatureInfo(info));
+  m_keyChain.setDefaultCertificate(subIdentity.getDefaultKey(), request);
+
+  return subIdentity;
+}
+
+v2::Certificate
+IdentityManagementFixture::addCertificate(const ndn::security::Key& key,
+                                          const std::string& issuer)
+{
+  ndn::Name certificateName = key.getName();
+  certificateName
+    .append(issuer)
+    .appendVersion();
+  v2::Certificate certificate;
+  certificate.setName(certificateName);
+
+  // set metainfo
+  certificate.setContentType(ndn::tlv::ContentType_Key);
+  certificate.setFreshnessPeriod(time::hours(1));
+
+  // set content
+  certificate.setContent(key.getPublicKey().data(), key.getPublicKey().size());
+
+  // set signature-info
+  ndn::SignatureInfo info;
+  info.setValidityPeriod(ndn::security::ValidityPeriod(time::system_clock::now(),
+                                                       time::system_clock::now() + time::days(10)));
+
+  m_keyChain.sign(certificate, ndn::signingByKey(key).setSignatureInfo(info));
+  return certificate;
+}
+
+} // namespace tests
+} // namespace nlsr
diff --git a/tests/identity-management-fixture.hpp b/tests/identity-management-fixture.hpp
new file mode 100644
index 0000000..acd75d0
--- /dev/null
+++ b/tests/identity-management-fixture.hpp
@@ -0,0 +1,106 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NLSR_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
+#define NLSR_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
+
+#include "boost-test.hpp"
+#include "test-home-fixture.hpp"
+
+#include <vector>
+
+#include <ndn-cxx/security/v2/key-chain.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
+
+namespace nlsr {
+namespace tests {
+
+class IdentityManagementBaseFixture : public TestHomeFixture<DefaultPibDir>
+{
+public:
+  ~IdentityManagementBaseFixture();
+
+  bool
+  saveCertToFile(const ndn::Data& obj, const std::string& filename);
+
+protected:
+  std::set<ndn::Name> m_identities;
+  std::set<std::string> m_certFiles;
+};
+
+/**
+ * @brief A test suite level fixture to help with identity management
+ *
+ * Test cases in the suite can use this fixture to create identities.  Identities,
+ * certificates, and saved certificates are automatically removed during test teardown.
+ */
+class IdentityManagementFixture : public IdentityManagementBaseFixture
+{
+public:
+  IdentityManagementFixture();
+
+  /**
+   * @brief Add identity @p identityName
+   * @return name of the created self-signed certificate
+   */
+  ndn::security::Identity
+  addIdentity(const ndn::Name& identityName, const ndn::KeyParams& params = ndn::KeyChain::getDefaultKeyParams());
+
+  /**
+   *  @brief Save identity certificate to a file
+   *  @param identity identity
+   *  @param filename file name, should be writable
+   *  @return whether successful
+   */
+  bool
+  saveCertificate(const ndn::security::Identity& identity, const std::string& filename);
+
+  /**
+   * @brief Issue a certificate for \p subidentityName signed by \p issuer
+   *
+   *  If identity does not exist, it is created.
+   *  A new key is generated as the default key for identity.
+   *  A default certificate for the key is signed by the issuer using its default certificate.
+   *
+   *  @return the sub identity
+   */
+  ndn::security::Identity
+  addSubCertificate(const ndn::Name& identityName, const ndn::security::Identity& issuer,
+                    const ndn::KeyParams& params = ndn::KeyChain::getDefaultKeyParams());
+
+  /**
+   * @brief Add a self-signed certificate to @p key with issuer ID @p issuer
+   */
+  ndn::security::v2::Certificate
+  addCertificate(const ndn::security::Key& key, const std::string& issuer);
+
+protected:
+  ndn::KeyChain m_keyChain;
+};
+
+} // namespace tests
+} // namespace nlsr
+
+#endif // NLSR_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
diff --git a/tests/main.cpp b/tests/main.cpp
index 1f6bd00..39380c5 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -1,7 +1,12 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
- *                           Regents of the University of California
+ * Copyright (c) 2014-2017,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
  *
  * This file is part of NLSR (Named-data Link State Routing).
  * See AUTHORS.md for complete list of NLSR authors and contributors.
@@ -16,12 +21,95 @@
  *
  * You should have received a copy of the GNU General Public License along with
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- *
- * \author Yingdi Yu <yingdi@cs.ucla.edu>
- *
- **/
+ */
 
-#define BOOST_TEST_MAIN 1
-#define BOOST_TEST_DYN_LINK 1
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_ALTERNATIVE_INIT_API
 
+#include <boost/version.hpp>
+
+#if BOOST_VERSION >= 106200
+// Boost.Test v3.3 (Boost 1.62) natively supports multi-logger output
 #include "boost-test.hpp"
+#else
+#define BOOST_TEST_NO_MAIN
+#include "boost-test.hpp"
+
+#include "boost-multi-log-formatter.hpp"
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+
+#include <fstream>
+#include <iostream>
+
+static bool
+init_tests()
+{
+  init_unit_test();
+
+  namespace po = boost::program_options;
+  namespace ut = boost::unit_test;
+
+  po::options_description extraOptions;
+  std::string logger;
+  std::string outputFile = "-";
+  extraOptions.add_options()
+    ("log_format2", po::value<std::string>(&logger), "Type of second log formatter: HRF or XML")
+    ("log_sink2", po::value<std::string>(&outputFile)->default_value(outputFile), "Second log sink, - for stdout")
+    ;
+  po::variables_map vm;
+  try {
+    po::store(po::command_line_parser(ut::framework::master_test_suite().argc,
+                                      ut::framework::master_test_suite().argv)
+                .options(extraOptions)
+                .run(),
+              vm);
+    po::notify(vm);
+  }
+  catch (const std::exception& e) {
+    std::cerr << "ERROR: " << e.what() << "\n"
+              << extraOptions << std::endl;
+    return false;
+  }
+
+  if (vm.count("log_format2") == 0) {
+    // second logger is not configured
+    return true;
+  }
+
+  std::shared_ptr<ut::unit_test_log_formatter> formatter;
+  if (logger == "XML") {
+    formatter = std::make_shared<ut::output::xml_log_formatter>();
+  }
+  else if (logger == "HRF") {
+    formatter = std::make_shared<ut::output::compiler_log_formatter>();
+  }
+  else {
+    std::cerr << "ERROR: only HRF or XML log formatter can be specified" << std::endl;
+    return false;
+  }
+
+  std::shared_ptr<std::ostream> output;
+  if (outputFile == "-") {
+    output = std::shared_ptr<std::ostream>(&std::cout, std::bind([]{}));
+  }
+  else {
+    output = std::make_shared<std::ofstream>(outputFile.c_str());
+  }
+
+  auto multiFormatter = new ut::output::multi_log_formatter;
+  multiFormatter->add(formatter, output);
+  ut::unit_test_log.set_formatter(multiFormatter);
+
+  return true;
+}
+
+int
+main(int argc, char* argv[])
+{
+  return ::boost::unit_test::unit_test_main(&init_tests, argc, argv);
+}
+
+#endif // BOOST_VERSION >= 106200
diff --git a/tests/publisher/publisher-fixture.hpp b/tests/publisher/publisher-fixture.hpp
index 9156c7b..4b702fc 100644
--- a/tests/publisher/publisher-fixture.hpp
+++ b/tests/publisher/publisher-fixture.hpp
@@ -30,6 +30,9 @@
 
 #include <ndn-cxx/util/dummy-client-face.hpp>
 #include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/security/pib/identity.hpp>
+
+#include <ndn-cxx/util/io.hpp>
 
 #include <boost/filesystem.hpp>
 
@@ -42,13 +45,16 @@
 {
 public:
   PublisherFixture()
-    : face(g_ioService, keyChain, {true, true})
-    , nlsr(g_ioService, g_scheduler, face, g_keyChain)
+    : face(m_ioService, m_keyChain, {true, true})
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , lsdb(nlsr.getLsdb())
   {
-    INIT_LOGGERS("/tmp/","TRACE");
+    INIT_LOGGERS("/tmp/", "TRACE");
     nlsr.getConfParameter().setNetwork("/ndn");
     nlsr.getConfParameter().setRouterName("/This/Router");
+
+    routerId = addIdentity("/ndn/This/Router");
+
     nlsr.initialize();
     face.processEvents(ndn::time::milliseconds(100));
   }
@@ -56,7 +62,7 @@
   void
   addAdjacency(AdjLsa& lsa, const std::string& name, const std::string& faceUri, double cost)
   {
-    Adjacent adjacency(name, ndn::util::FaceUri(faceUri), cost, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent adjacency(name, ndn::FaceUri(faceUri), cost, Adjacent::STATUS_ACTIVE, 0, 0);
     lsa.addAdjacent(std::move(adjacency));
   }
 
@@ -148,10 +154,11 @@
 
 public:
   ndn::util::DummyClientFace face;
-  ndn::KeyChain keyChain;
 
   Nlsr nlsr;
   Lsdb& lsdb;
+
+  ndn::security::pib::Identity routerId;
 };
 
 } // namespace test
diff --git a/tests/publisher/test-segment-publisher.cpp b/tests/publisher/test-segment-publisher.cpp
index c6b4fba..e1a7232 100644
--- a/tests/publisher/test-segment-publisher.cpp
+++ b/tests/publisher/test-segment-publisher.cpp
@@ -26,6 +26,7 @@
 #include "publisher/segment-publisher.hpp"
 
 #include "../boost-test.hpp"
+#include "../test-common.hpp"
 
 #include <ndn-cxx/encoding/tlv.hpp>
 #include <ndn-cxx/util/dummy-client-face.hpp>
@@ -36,14 +37,17 @@
 namespace nlsr {
 namespace tests {
 
+using namespace nlsr::test;
+
 template<int64_t N=10000>
 class TestSegmentPublisher : public SegmentPublisher<ndn::util::DummyClientFace>
 {
 public:
   TestSegmentPublisher(ndn::util::DummyClientFace& face,
                        ndn::KeyChain& keyChain,
+                       ndn::security::SigningInfo& signingInfo,
                        const ndn::time::milliseconds freshnessPeriod)
-    : SegmentPublisher(face, keyChain, freshnessPeriod)
+    : SegmentPublisher(face, keyChain, signingInfo, freshnessPeriod)
     , m_totalPayloadLength(0)
   {
 
@@ -72,10 +76,10 @@
   generate(ndn::EncodingBuffer& outBuffer)
   {
     size_t totalLength = 0;
-    for (int64_t i = 0; i < N; i++)
-      {
+    for (int64_t i = 0; i < N; i++) {
         totalLength += prependNonNegativeIntegerBlock(outBuffer, ndn::tlv::Content, i);
-      }
+    }
+
     m_totalPayloadLength += totalLength;
     return totalLength;
   }
@@ -85,13 +89,13 @@
 };
 
 template<int64_t N>
-class SegmentPublisherFixture
+class SegmentPublisherFixture : public BaseFixture
 {
 public:
   SegmentPublisherFixture()
-    : m_face(std::make_shared<ndn::util::DummyClientFace>())
+    : m_face(std::make_shared<ndn::util::DummyClientFace>(m_ioService, m_keyChain))
     , m_expectedFreshnessPeriod(ndn::time::milliseconds(111))
-    , m_publisher(*m_face, m_keyChain, m_expectedFreshnessPeriod)
+    , m_publisher(*m_face, m_keyChain, m_signingInfo, m_expectedFreshnessPeriod)
     , m_publishingPrefix("/localhost/nfd/SegmentPublisherFixture")
   {
   }
@@ -106,10 +110,9 @@
     m_buffer.appendByteArray(payload.value(), payload.value_size());
 
     // uint64_t segmentNo = data.getName()[-1].toSegment();
-    if (data.getFinalBlockId() != data.getName()[-1])
-      {
+    if (data.getFinalBlockId() != data.getName()[-1]) {
         return;
-      }
+    }
 
     // wrap data in a single Content TLV for easy parsing
     m_buffer.prependVarNumber(m_buffer.size());
@@ -138,7 +141,7 @@
   const ndn::time::milliseconds m_expectedFreshnessPeriod;
   TestSegmentPublisher<N> m_publisher;
   ndn::EncodingBuffer m_buffer;
-  ndn::KeyChain m_keyChain;
+  ndn::security::SigningInfo m_signingInfo;
   const ndn::Name m_publishingPrefix;
 };
 
diff --git a/tests/security/test-certificate-store.cpp b/tests/security/test-certificate-store.cpp
index de3207e..a37e6d8 100644
--- a/tests/security/test-certificate-store.cpp
+++ b/tests/security/test-certificate-store.cpp
@@ -30,28 +30,20 @@
 namespace test {
 
 using std::shared_ptr;
+using namespace nlsr::test;
 
-class CertificateStoreFixture
+class CertificateStoreFixture : public BaseFixture
 {
 public:
   CertificateStoreFixture()
   {
-    // Create certificate
-    ndn::Name identity("/TestNLSR/identity");
-    identity.appendVersion();
-
-    ndn::KeyChain keyChain;
-    keyChain.createIdentity(identity);
-    ndn::Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
-    certificate = keyChain.getCertificate(certName);
-
-    BOOST_REQUIRE(certificate != nullptr);
-
-    certificateKey = certificate->getName().getPrefix(-1);
+    auto identity = addIdentity("/TestNLSR/identity");
+    certificateKey = identity.getDefaultKey().getName();
+    certificate = identity.getDefaultKey().getDefaultCertificate();
   }
 
 public:
-  std::shared_ptr<ndn::IdentityCertificate> certificate;
+  ndn::security::v2::Certificate certificate;
   ndn::Name certificateKey;
 };
 
@@ -64,7 +56,7 @@
   BOOST_REQUIRE(store.find(certificateKey) == nullptr);
   store.insert(certificate);
 
-  BOOST_CHECK(*store.find(certificateKey) == *certificate);
+  BOOST_CHECK(*store.find(certificateKey) == certificate);
 
   store.clear();
   BOOST_REQUIRE(store.find(certificateKey) == nullptr);
diff --git a/tests/test-adjacency-list.cpp b/tests/test-adjacency-list.cpp
index 1488daa..aaa0915 100644
--- a/tests/test-adjacency-list.cpp
+++ b/tests/test-adjacency-list.cpp
@@ -64,7 +64,7 @@
 
 BOOST_AUTO_TEST_CASE(findAdjacentByFaceUri)
 {
-  ndn::util::FaceUri faceUri("udp4://10.0.0.1:6363");
+  ndn::FaceUri faceUri("udp4://10.0.0.1:6363");
   Adjacent adj1("/ndn/test/1", faceUri, 10, Adjacent::STATUS_INACTIVE, 0, 0);
   AdjacencyList adjList;
   adjList.insert(adj1);
diff --git a/tests/test-adjacent.cpp b/tests/test-adjacent.cpp
index 8bd0c26..512cec1 100644
--- a/tests/test-adjacent.cpp
+++ b/tests/test-adjacent.cpp
@@ -34,7 +34,7 @@
 BOOST_AUTO_TEST_CASE(OperatorEquals)
 {
   const ndn::Name ADJ_NAME_1 = "name1";
-  const ndn::util::FaceUri ADJ_URI_1 = ndn::util::FaceUri("udp4://10.0.0.1:8000");
+  const ndn::FaceUri ADJ_URI_1 = ndn::FaceUri("udp4://10.0.0.1:8000");
   const double ADJ_LINK_COST_1 = 1;
   Adjacent adjacent1(ADJ_NAME_1);
   Adjacent adjacent2(ADJ_NAME_1);
@@ -82,7 +82,7 @@
 {
   const ndn::Name ADJ_NAME_1 = "name1";
   const ndn::Name ADJ_NAME_2 = "name2";
-  const ndn::util::FaceUri ADJ_URI_1 = ndn::util::FaceUri("udp4://10.0.0.1:8000");
+  const ndn::FaceUri ADJ_URI_1 = ndn::FaceUri("udp4://10.0.0.1:8000");
   Adjacent adjacent1(ADJ_NAME_1);
   Adjacent adjacent2(ADJ_NAME_2);
   adjacent1.setFaceUri(ADJ_URI_1);
diff --git a/tests/test-common.cpp b/tests/test-common.cpp
index e6b5e78..11ca06d 100644
--- a/tests/test-common.cpp
+++ b/tests/test-common.cpp
@@ -35,7 +35,7 @@
 }
 
 MockNfdMgmtFixture::MockNfdMgmtFixture()
-  : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
+  : m_face(m_ioService, m_keyChain, {true, true})
 {
 }
 
@@ -52,11 +52,11 @@
     steadyClock->advance(tick);
     systemClock->advance(tick);
 
-    if (g_ioService.stopped()) {
-      g_ioService.reset();
+    if (m_ioService.stopped()) {
+      m_ioService.reset();
     }
 
-    g_ioService.poll();
+    m_ioService.poll();
   }
 }
 
diff --git a/tests/test-common.hpp b/tests/test-common.hpp
index dcba6c0..ef9c2de 100644
--- a/tests/test-common.hpp
+++ b/tests/test-common.hpp
@@ -23,6 +23,7 @@
 #define NLSR_TEST_COMMON_HPP
 
 #include "common.hpp"
+#include "identity-management-fixture.hpp"
 
 #include <boost/asio.hpp>
 #include <boost/test/unit_test.hpp>
@@ -50,18 +51,17 @@
   return data;
 }
 
-class BaseFixture
+class BaseFixture : public tests::IdentityManagementFixture
 {
 public:
   BaseFixture()
-    : g_scheduler(g_ioService)
+    : m_scheduler(m_ioService)
   {
   }
 
 protected:
-  boost::asio::io_service g_ioService;
-  ndn::Scheduler g_scheduler;
-  ndn::KeyChain g_keyChain;
+  boost::asio::io_service m_ioService;
+  ndn::Scheduler m_scheduler;
 };
 
 class UnitTestTimeFixture : public BaseFixture
@@ -140,12 +140,12 @@
 
     // These warnings assist in debugging when nfdc does not receive StatusDataset.
     // They usually indicate a misspelled prefix or incorrect timing in the test case.
-    if (face->sentInterests.empty()) {
+    if (m_face.sentInterests.empty()) {
       BOOST_WARN_MESSAGE(false, "no Interest expressed");
     }
     else {
-      BOOST_WARN_MESSAGE(face->sentInterests.back().getName().isPrefixOf(name),
-                         "last Interest " << face->sentInterests.back().getName() <<
+      BOOST_WARN_MESSAGE(m_face.sentInterests.back().getName().isPrefixOf(name),
+                         "last Interest " << m_face.sentInterests.back().getName() <<
                          " cannot be satisfied by this Data " << name);
     }
 
@@ -153,14 +153,14 @@
     data->setFinalBlockId(name[-1]);
     data->setContent(std::forward<ContentArgs>(contentArgs)...);
     this->signDatasetReply(*data);
-    face->receive(*data);
+    m_face.receive(*data);
   }
 
   virtual void
   signDatasetReply(ndn::Data& data);
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
+  ndn::util::DummyClientFace m_face;
 };
 
 } // namespace test
diff --git a/tests/test-conf-file-processor.cpp b/tests/test-conf-file-processor.cpp
index 479bba1..0400b05 100644
--- a/tests/test-conf-file-processor.cpp
+++ b/tests/test-conf-file-processor.cpp
@@ -25,6 +25,7 @@
 #include "nlsr.hpp"
 
 #include <fstream>
+
 #include <boost/test/unit_test.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/algorithm/string.hpp>
@@ -142,11 +143,11 @@
 {
 public:
   ConfFileProcessorFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>())
-    , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+    : face(m_ioService, m_keyChain)
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , CONFIG_FILE("unit-test-nlsr.conf")
-    , m_logConfigFileName(boost::filesystem::unique_path().native())
-    , m_logFileName(boost::filesystem::unique_path().native())
+    , m_logConfigFileName(boost::filesystem::unique_path().string())
+    , m_logFileName(boost::filesystem::unique_path().string())
   {
   }
 
@@ -159,7 +160,8 @@
     boost::filesystem::remove(boost::filesystem::path(getLogFileName()));
   }
 
-  bool processConfigurationString(std::string confString)
+  bool
+  processConfigurationString(std::string confString)
   {
     std::ofstream config;
     config.open("unit-test-nlsr.conf");
@@ -210,7 +212,7 @@
   }
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
+  ndn::util::DummyClientFace face;
   Nlsr nlsr;
 
 private:
@@ -498,64 +500,51 @@
 
 BOOST_AUTO_TEST_CASE(LoadCertToPublish)
 {
-  ndn::Name identity("/TestNLSR/identity");
-  identity.appendVersion();
+  auto identity = addIdentity("/TestNLSR/identity");
+  saveCertificate(identity, "cert-to-publish.cert");
 
-  ndn::KeyChain keyChain;
-  keyChain.createIdentity(identity);
-  ndn::Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
-  std::shared_ptr<ndn::IdentityCertificate> certificate = keyChain.getCertificate(certName);
-
-  const boost::filesystem::path CERT_PATH =
-      (boost::filesystem::current_path() / std::string("cert-to-publish.cert"));
-  ndn::io::save(*certificate, CERT_PATH.string());
-
-  const std::string SECTION_SECURITY =
-  "security\n"
-  "{\n"
-  "  validator\n"
-  "  {\n"
-  "    trust-anchor\n"
-  "    {\n"
-  "      type any\n"
-  "    }\n"
-  "  }\n"
-  "  prefix-update-validator\n"
-  "  {\n"
-  "    trust-anchor\n"
-  "    {\n"
-  "      type any\n"
-  "    }\n"
-  "  }\n"
-  "  cert-to-publish \"cert-to-publish.cert\"\n"
-  "}\n\n";
+  const std::string SECTION_SECURITY = R"CONF(
+      security
+      {
+        validator
+        {
+          trust-anchor
+          {
+            type any
+          }
+        }
+        prefix-update-validator
+        {
+          trust-anchor
+          {
+            type any
+          }
+        }
+        cert-to-publish "cert-to-publish.cert"
+      }
+    )CONF";
 
   BOOST_CHECK(processConfigurationString(SECTION_SECURITY));
 
   // Certificate should now be in the CertificateStore
-  const security::CertificateStore& certStore = nlsr.getCertificateStore();
-  const ndn::Name certKey = certificate->getName().getPrefix(-1);
-
-  BOOST_CHECK(certStore.find(certKey) != nullptr);
-
-  // Cleanup
-  keyChain.deleteIdentity(identity);
-  boost::filesystem::remove(CERT_PATH);
+  security::CertificateStore& certStore = nlsr.getCertificateStore();
+  BOOST_CHECK(certStore.find(identity.getDefaultKey().getName()) != nullptr);
 }
 
 BOOST_AUTO_TEST_CASE(PrefixUpdateValidatorOptional) // Bug #2814
 {
-  const std::string SECTION_SECURITY =
-  "security\n"
-  "{\n"
-  "  validator\n"
-  "  {\n"
-  "    trust-anchor\n"
-  "    {\n"
-  "      type any\n"
-  "    }\n"
-  "  }\n"
-  "}\n\n";
+  const std::string SECTION_SECURITY = R"CONF(
+      security
+      {
+        validator
+        {
+          trust-anchor
+          {
+            type any
+          }
+        }
+      }
+    )CONF";
 
   BOOST_CHECK(processConfigurationString(SECTION_SECURITY));
 }
diff --git a/tests/test-fib.cpp b/tests/test-fib.cpp
index 84642f1..80408eb 100644
--- a/tests/test-fib.cpp
+++ b/tests/test-fib.cpp
@@ -36,24 +36,23 @@
 {
 public:
   FibFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>())
+    : face(std::make_shared<ndn::util::DummyClientFace>(m_keyChain))
     , interests(face->sentInterests)
   {
     INIT_LOGGERS("/tmp", "DEBUG");
 
-    Adjacent neighbor1(router1Name, ndn::util::FaceUri(router1FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
+    Adjacent neighbor1(router1Name, ndn::FaceUri(router1FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
     adjacencies.insert(neighbor1);
 
-    Adjacent neighbor2(router2Name, ndn::util::FaceUri(router2FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
+    Adjacent neighbor2(router2Name, ndn::FaceUri(router2FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
     adjacencies.insert(neighbor2);
 
-    Adjacent neighbor3(router3Name, ndn::util::FaceUri(router3FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
+    Adjacent neighbor3(router3Name, ndn::FaceUri(router3FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
     adjacencies.insert(neighbor3);
 
     conf.setMaxFacesPerPrefix(2);
 
-    fib = std::make_shared<Fib>(std::ref(*face), std::ref(g_scheduler), std::ref(adjacencies),
-                                std::ref(conf), keyChain);
+    fib = std::make_shared<Fib>(*face, m_scheduler, adjacencies, conf, m_keyChain);
 
     fib->m_faceMap.update(router1FaceUri, router1FaceId);
     fib->m_faceMap.update(router2FaceUri, router2FaceId);
@@ -62,7 +61,6 @@
 
 public:
   std::shared_ptr<ndn::util::DummyClientFace> face;
-  ndn::KeyChain keyChain;
   std::shared_ptr<Fib> fib;
 
   AdjacencyList adjacencies;
diff --git a/tests/test-home-fixture.hpp b/tests/test-home-fixture.hpp
new file mode 100644
index 0000000..a3ced4e
--- /dev/null
+++ b/tests/test-home-fixture.hpp
@@ -0,0 +1,132 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NLSR_TEST_HOME_FIXTURE_HPP
+#define NLSR_TEST_HOME_FIXTURE_HPP
+
+#include "boost-test.hpp"
+
+#include <fstream>
+
+#include <ndn-cxx/security/v2/key-chain.hpp>
+
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
+
+namespace nlsr {
+namespace tests {
+
+/**
+ * @brief Fixture to adjust/restore NDN_CLIENT_PIB and NDN_CLIENT_TPM paths
+ *
+ * Note that the specified PATH will be removed after fixture is destroyed.
+ * **Do not specify non-temporary paths.**
+ */
+template<class Path>
+class PibDirFixture
+{
+public:
+  PibDirFixture()
+    : m_pibDir(Path().PATH)
+  {
+    if (getenv("NDN_CLIENT_PIB") != nullptr) {
+      m_oldPib = getenv("NDN_CLIENT_PIB");
+    }
+    if (getenv("NDN_CLIENT_TPM") != nullptr) {
+      m_oldTpm = getenv("NDN_CLIENT_TPM");
+    }
+
+    /// @todo Consider change to an in-memory PIB/TPM
+    setenv("NDN_CLIENT_PIB", ("pib-sqlite3:" + m_pibDir).c_str(), true);
+    setenv("NDN_CLIENT_TPM", ("tpm-file:" + m_pibDir).c_str(), true);
+  }
+
+  ~PibDirFixture()
+  {
+    if (!m_oldPib.empty()) {
+      setenv("NDN_CLIENT_PIB", m_oldPib.c_str(), true);
+    }
+    else {
+      unsetenv("NDN_CLIENT_PIB");
+    }
+
+    if (!m_oldTpm.empty()) {
+      setenv("NDN_CLIENT_TPM", m_oldTpm.c_str(), true);
+    }
+    else {
+      unsetenv("NDN_CLIENT_TPM");
+    }
+
+    boost::filesystem::remove_all(m_pibDir);
+    //const_cast<std::string&>(ndn::security::v2::KeyChain::getDefaultPibLocator()).clear();
+    //const_cast<std::string&>(ndn::security::v2::KeyChain::getDefaultTpmLocator()).clear();
+  }
+
+protected:
+  const std::string m_pibDir;
+
+private:
+  std::string m_oldPib;
+  std::string m_oldTpm;
+};
+
+/**
+ * @brief Extension of PibDirFixture to set TEST_HOME variable and allow config file creation
+ */
+template<class Path>
+class TestHomeFixture : public PibDirFixture<Path>
+{
+public:
+  TestHomeFixture()
+  {
+    setenv("TEST_HOME", this->m_pibDir.c_str(), true);
+  }
+
+  ~TestHomeFixture()
+  {
+    unsetenv("TEST_HOME");
+  }
+
+  void
+  createClientConf(std::initializer_list<std::string> lines)
+  {
+    boost::filesystem::create_directories(boost::filesystem::path(this->m_pibDir) / ".ndn");
+    std::ofstream of((boost::filesystem::path(this->m_pibDir) / ".ndn" / "client.conf").c_str());
+    for (auto line : lines) {
+      boost::replace_all(line, "%PATH%", this->m_pibDir);
+      of << line << std::endl;
+    }
+  }
+};
+
+struct DefaultPibDir
+{
+  const std::string PATH = "build/keys";
+};
+
+} // namespace tests
+} // namespace nlsr
+
+#endif // NLSR_TEST_HOME_FIXTURE_HPP
diff --git a/tests/test-hyperbolic-calculator.cpp b/tests/test-hyperbolic-calculator.cpp
index c894c98..dc0cd18 100644
--- a/tests/test-hyperbolic-calculator.cpp
+++ b/tests/test-hyperbolic-calculator.cpp
@@ -45,8 +45,8 @@
 {
 public:
   HyperbolicCalculatorFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>())
-    , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+    : face(m_ioService, m_keyChain)
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , routingTable(nlsr.getRoutingTable())
     , adjacencies(nlsr.getAdjacencyList())
     , lsdb(nlsr.getLsdb())
@@ -59,9 +59,9 @@
   {
     INIT_LOGGERS("/tmp", "TRACE");
 
-    Adjacent a(ROUTER_A_NAME, ndn::util::FaceUri(ROUTER_A_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
-    Adjacent b(ROUTER_B_NAME, ndn::util::FaceUri(ROUTER_B_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
-    Adjacent c(ROUTER_C_NAME, ndn::util::FaceUri(ROUTER_C_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent a(ROUTER_A_NAME, ndn::FaceUri(ROUTER_A_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent b(ROUTER_B_NAME, ndn::FaceUri(ROUTER_B_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent c(ROUTER_C_NAME, ndn::FaceUri(ROUTER_C_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
 
     // Router A
     adjacencies.insert(b);
@@ -149,7 +149,7 @@
   }
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
+  ndn::util::DummyClientFace face;
   Nlsr nlsr;
   Map map;
 
diff --git a/tests/test-link-state-calculator.cpp b/tests/test-link-state-calculator.cpp
index d0605f3..31c9abf 100644
--- a/tests/test-link-state-calculator.cpp
+++ b/tests/test-link-state-calculator.cpp
@@ -41,8 +41,8 @@
 {
 public:
   LinkStateCalculatorFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
-    , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+    : face(m_ioService, m_keyChain)
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , routingTable(nlsr.getRoutingTable())
     , lsdb(nlsr.getLsdb())
   {
@@ -60,9 +60,9 @@
     conf.setRouterName("/a");
     conf.buildRouterPrefix();
 
-    Adjacent a(ROUTER_A_NAME, ndn::util::FaceUri(ROUTER_A_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
-    Adjacent b(ROUTER_B_NAME, ndn::util::FaceUri(ROUTER_B_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
-    Adjacent c(ROUTER_C_NAME, ndn::util::FaceUri(ROUTER_C_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent a(ROUTER_A_NAME, ndn::FaceUri(ROUTER_A_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent b(ROUTER_B_NAME, ndn::FaceUri(ROUTER_B_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent c(ROUTER_C_NAME, ndn::FaceUri(ROUTER_C_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
 
     // Router A
     b.setLinkCost(LINK_AB_COST);
@@ -101,7 +101,7 @@
   }
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
+  ndn::util::DummyClientFace face;
   Nlsr nlsr;
   Map map;
 
diff --git a/tests/test-lsa-rule.cpp b/tests/test-lsa-rule.cpp
index 0ec3ff5..e776942 100644
--- a/tests/test-lsa-rule.cpp
+++ b/tests/test-lsa-rule.cpp
@@ -37,38 +37,32 @@
 namespace nlsr {
 namespace test {
 
-class LsaRuleFixture : public nlsr::test::BaseFixture
+class LsaRuleFixture : public nlsr::test::UnitTestTimeFixture
 {
 public:
   LsaRuleFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
-    , rootId(ndn::Name("ndn"))
-    , siteIdentity(ndn::Name("/ndn/edu/test-site"))
-    , opIdentity(ndn::Name(siteIdentity).append(ndn::Name("%C1.Operator/op1")))
-    , routerId(ndn::Name("/ndn/edu/test-site/%C1.Router/router1"))
-    , nlsr(g_ioService, g_scheduler, *face, g_keyChain)
+    : face(m_ioService, m_keyChain, {true, true})
+    , rootIdName("/ndn")
+    , siteIdentityName("/ndn/edu/test-site")
+    , opIdentityName("/ndn/edu/test-site/%C1.Operator/op1")
+    , routerIdName("/ndn/edu/test-site/%C1.Router/router1")
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , ROOT_CERT_PATH(boost::filesystem::current_path() / std::string("root.cert"))
   {
-    try {
-      keyChain.deleteIdentity(rootId);
-      keyChain.deleteIdentity(siteIdentity);
-      keyChain.deleteIdentity(opIdentity);
-      keyChain.deleteIdentity(routerId);
-    }
-    catch (const std::exception& e) {
-    }
+    rootId = addIdentity(rootIdName);
+    siteIdentity = addSubCertificate(siteIdentityName, rootId);
+    opIdentity = addSubCertificate(opIdentityName, siteIdentity);
+    routerId = addSubCertificate(routerIdName, opIdentity);
 
-    createCert(rootId, rootCertName, rootCert, rootId);
-    BOOST_REQUIRE(rootCert != nullptr);
+    saveCertificate(rootId, ROOT_CERT_PATH.string());
 
-    createCert(siteIdentity, siteCertName, siteCert, rootId);
-    BOOST_REQUIRE(siteCert != nullptr);
-
-    createCert(opIdentity, opCertName, opCert, siteIdentity);
-    BOOST_REQUIRE(opCert != nullptr);
-
-    createCert(routerId, routerCertName, routerCert, opIdentity);
-    BOOST_REQUIRE(routerCert != nullptr);
+    auto load = [this] (const ndn::security::Identity& id) {
+      nlsr.loadCertToPublish(id.getDefaultKey().getDefaultCertificate());
+    };
+    load(rootId);
+    load(siteIdentity);
+    load(opIdentity);
+    load(routerId);
 
     // Loading the security section's validator part into the validator
     // See conf file processor for more details
@@ -99,97 +93,52 @@
 
     // Initialize NLSR to initialize the keyChain
     nlsr.initialize();
-  }
 
-  void
-  createCert(ndn::Name& identity, ndn::Name& certName, std::shared_ptr<IdentityCertificate>& cert, const ndn::Name& signer)
-  {
-    ndn::Name keyName = keyChain.generateRsaKeyPairAsDefault(identity, true);
+    this->advanceClocks(ndn::time::milliseconds(10));
 
-    cert = std::make_shared<ndn::IdentityCertificate>();
-    std::shared_ptr<ndn::PublicKey> pubKey = keyChain.getPublicKey(keyName);
-    certName = keyName.getPrefix(-1);
-    certName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
-    cert->setName(certName);
-    cert->setNotBefore(time::system_clock::now() - time::days(1));
-    cert->setNotAfter(time::system_clock::now() + time::days(1));
-    cert->setPublicKeyInfo(*pubKey);
-    cert->addSubjectDescription(CertificateSubjectDescription(ndn::oid::ATTRIBUTE_NAME,
-                                                                keyName.toUri()));
-    cert->encode();
-
-    // root is self signed and root.cert is saved
-    if (signer == identity) {
-      keyChain.selfSign(*cert);
-
-      keyChain.addCertificateAsIdentityDefault(*cert);
-
-      nlsr.loadCertToPublish(cert);
-
-      ndn::io::save(*cert, ROOT_CERT_PATH.string());
-    }
-    else {
-      ndn::security::SigningInfo signingInfo;
-      signingInfo.setSigningIdentity(signer);
-      keyChain.sign(*cert, signingInfo);
-
-      keyChain.addCertificateAsIdentityDefault(*cert);
-
-      nlsr.loadCertToPublish(cert);
-    }
-  }
-
-  ~LsaRuleFixture()
-  {
-    keyChain.deleteIdentity(rootId);
-    keyChain.deleteIdentity(siteIdentity);
-    keyChain.deleteIdentity(opIdentity);
-    keyChain.deleteIdentity(routerId);
-
-    boost::filesystem::remove(ROOT_CERT_PATH);
-  }
+    face.sentInterests.clear();
+   }
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
-  ndn::KeyChain keyChain;
+  ndn::util::DummyClientFace face;
 
-  ndn::Name rootId, siteIdentity, opIdentity, routerId;
-  ndn::Name rootCertName, siteCertName, opCertName, routerCertName;
-  std::shared_ptr<IdentityCertificate> rootCert, siteCert, opCert, routerCert;
+  ndn::Name rootIdName, siteIdentityName, opIdentityName, routerIdName;
+  ndn::security::pib::Identity rootId, siteIdentity, opIdentity, routerId;
 
   Nlsr nlsr;
 
   const boost::filesystem::path ROOT_CERT_PATH;
+
+  //std::function<void(const ndn::Interest& interest)> processInterest;
 };
 
 BOOST_FIXTURE_TEST_SUITE(TestLsaDataValidation, LsaRuleFixture)
 
 BOOST_AUTO_TEST_CASE(ValidateCorrectLSA)
 {
-  ndn::Name lsaInterestName = nlsr.getConfParameter().getLsaPrefix();
-  lsaInterestName.append(nlsr.getConfParameter().getSiteName());
-  lsaInterestName.append(nlsr.getConfParameter().getRouterName());
+  ndn::Name lsaDataName = nlsr.getConfParameter().getLsaPrefix();
+  lsaDataName.append(nlsr.getConfParameter().getSiteName());
+  lsaDataName.append(nlsr.getConfParameter().getRouterName());
 
   // Append LSA type
-  lsaInterestName.append(std::to_string(Lsa::Type::NAME));
+  lsaDataName.append(std::to_string(Lsa::Type::NAME));
 
   // This would be the sequence number of its own NameLsa
-  lsaInterestName.appendNumber(nlsr.getLsdb().getSequencingManager().getNameLsaSeq());
+  lsaDataName.appendNumber(nlsr.getLsdb().getSequencingManager().getNameLsaSeq());
 
   // Append version, segmentNo
-  lsaInterestName.appendNumber(1).appendNumber(1);
+  lsaDataName.appendNumber(1).appendNumber(1);
 
-  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
-  data->setName(lsaInterestName);
-  data->setFreshnessPeriod(ndn::time::seconds(10));
+  ndn::Data data(lsaDataName);
+  data.setFreshnessPeriod(ndn::time::seconds(10));
 
   // Sign data with NLSR's key
-  nlsr.getKeyChain().sign(*data, ndn::security::signingByCertificate(nlsr.getDefaultCertName()));
+  nlsr.getKeyChain().sign(data, nlsr.getSigningInfo());
 
   // Make NLSR validate data signed by its own key
-  nlsr.getValidator().validate(*data,
-                               [] (const std::shared_ptr<const Data>&) { BOOST_CHECK(true); },
-                               [] (const std::shared_ptr<const Data>&, const std::string&) {
+  nlsr.getValidator().validate(data,
+                               [] (const Data&) { BOOST_CHECK(true); },
+                               [] (const Data&, const ndn::security::v2::ValidationError&) {
                                  BOOST_CHECK(false);
                                });
 }
@@ -197,28 +146,26 @@
 BOOST_AUTO_TEST_CASE(DoNotValidateIncorrectLSA)
 {
   // getSubName removes the /localhop compnonent from /localhop/ndn/NLSR/LSA
-  ndn::Name lsaInterestName = nlsr.getConfParameter().getLsaPrefix().getSubName(1);
-  lsaInterestName.append(nlsr.getConfParameter().getSiteName());
-  lsaInterestName.append(nlsr.getConfParameter().getRouterName());
+  ndn::Name lsaDataName = nlsr.getConfParameter().getLsaPrefix().getSubName(1);
+  lsaDataName.append(nlsr.getConfParameter().getSiteName());
+  lsaDataName.append(nlsr.getConfParameter().getRouterName());
 
   // Append LSA type
-  lsaInterestName.append(std::to_string(Lsa::Type::NAME));
+  lsaDataName.append(std::to_string(Lsa::Type::NAME));
 
   // This would be the sequence number of its own NameLsa
-  lsaInterestName.appendNumber(nlsr.getLsdb().getSequencingManager().getNameLsaSeq());
+  lsaDataName.appendNumber(nlsr.getLsdb().getSequencingManager().getNameLsaSeq());
 
   // Append version, segmentNo
-  lsaInterestName.appendNumber(1).appendNumber(1);
+  lsaDataName.appendNumber(1).appendNumber(1);
 
-  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>();
-  data->setName(lsaInterestName);
-  data->setFreshnessPeriod(ndn::time::seconds(10));
-  nlsr.getKeyChain().sign(*data, ndn::security::signingByCertificate(nlsr.getDefaultCertName()));
+  ndn::Data data(lsaDataName);
+  data.setFreshnessPeriod(ndn::time::seconds(10));
 
   // Make NLSR validate data signed by its own key
-  nlsr.getValidator().validate(*data,
-                               [] (const std::shared_ptr<const Data>&) { BOOST_CHECK(false); },
-                               [] (const std::shared_ptr<const Data>&, const std::string&) {
+  nlsr.getValidator().validate(data,
+                               [] (const Data&) { BOOST_CHECK(false); },
+                               [] (const Data&, const ndn::security::v2::ValidationError&) {
                                  BOOST_CHECK(true);
                                });
 }
diff --git a/tests/test-lsa.cpp b/tests/test-lsa.cpp
index c5b3ffd..20fc1c1 100644
--- a/tests/test-lsa.cpp
+++ b/tests/test-lsa.cpp
@@ -161,9 +161,9 @@
 
   //If we don't do this the test will fail
   //Adjacent has default cost of 10 but no default
-  //connecting face URI, so deserialize fails
-  adj1.setFaceUri(ndn::util::FaceUri("udp://10.0.0.1"));
-  adj2.setFaceUri(ndn::util::FaceUri("udp://10.0.0.2"));
+  //connecting face URI, so initializeFromContent fails
+  adj1.setFaceUri(ndn::FaceUri("udp://10.0.0.1"));
+  adj2.setFaceUri(ndn::FaceUri("udp://10.0.0.2"));
 
   AdjacencyList adjList;
   adjList.insert(adj1);
diff --git a/tests/test-lsdb.cpp b/tests/test-lsdb.cpp
index 2a4d11c..0142579 100644
--- a/tests/test-lsdb.cpp
+++ b/tests/test-lsdb.cpp
@@ -29,17 +29,19 @@
 #include <ndn-cxx/util/dummy-client-face.hpp>
 #include <ndn-cxx/util/segment-fetcher.hpp>
 
+#include <unistd.h>
+
 namespace nlsr {
 namespace test {
 
 using std::shared_ptr;
 
-class LsdbFixture : public BaseFixture
+class LsdbFixture : public UnitTestTimeFixture
 {
 public:
   LsdbFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
-    , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+    : face(m_ioService, m_keyChain)
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , lsdb(nlsr.getLsdb())
     , conf(nlsr.getConfParameter())
     , REGISTER_COMMAND_PREFIX("/localhost/nfd/rib")
@@ -47,12 +49,14 @@
   {
     conf.setNetwork("/ndn");
     conf.setSiteName("/site");
-    conf.setRouterName("/%C1.router/this-router");
+    conf.setRouterName("/%C1.Router/this-router");
+
+    addIdentity("/ndn/site/%C1.Router/this-router");
 
     nlsr.initialize();
 
-    face->processEvents(ndn::time::milliseconds(1));
-    face->sentInterests.clear();
+    advanceClocks(ndn::time::milliseconds(1), 10);
+    face.sentInterests.clear();
 
     INIT_LOGGERS("/tmp", "DEBUG");
   }
@@ -89,7 +93,7 @@
   }
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
+  ndn::util::DummyClientFace face;
   Nlsr nlsr;
   Lsdb& lsdb;
   ConfParameter& conf;
@@ -109,9 +113,9 @@
   oldInterestName.appendNumber(oldSeqNo);
 
   lsdb.expressInterest(oldInterestName, 0);
-  face->processEvents(ndn::time::milliseconds(1));
+  advanceClocks(ndn::time::milliseconds(1), 10);
 
-  std::vector<ndn::Interest>& interests = face->sentInterests;
+  std::vector<ndn::Interest>& interests = face.sentInterests;
 
   BOOST_REQUIRE(interests.size() > 0);
 
@@ -129,7 +133,7 @@
   // Simulate an LSA interest timeout
   lsdb.onFetchLsaError(ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT, "Timeout",
                        oldInterestName, 0, deadline, interestName, oldSeqNo);
-  face->processEvents(ndn::time::milliseconds(1));
+  advanceClocks(ndn::time::milliseconds(1), 10);
 
   BOOST_REQUIRE(interests.size() > 0);
 
@@ -147,7 +151,7 @@
   newInterestName.appendNumber(newSeqNo);
 
   lsdb.expressInterest(newInterestName, 0);
-  face->processEvents(ndn::time::milliseconds(1));
+  advanceClocks(ndn::time::milliseconds(1), 10);
 
   BOOST_REQUIRE(interests.size() > 0);
 
@@ -163,7 +167,7 @@
   // Simulate an LSA interest timeout where the sequence number is outdated
   lsdb.onFetchLsaError(ndn::util::SegmentFetcher::ErrorCode::INTEREST_TIMEOUT, "Timeout",
                        oldInterestName, 0, deadline, interestName, oldSeqNo);
-  face->processEvents(ndn::time::milliseconds(1));
+  advanceClocks(ndn::time::milliseconds(1), 10);
 
   // Interest should not be expressed for outdated sequence number
   BOOST_CHECK_EQUAL(interests.size(), 0);
@@ -191,18 +195,21 @@
   interestName.appendNumber(seqNo);
 
   ndn::Interest interest(interestName);
+  lsdb.processInterest(ndn::Name(), interest);
+  advanceClocks(ndn::time::milliseconds(1), 10);
+  face.sentData.clear();
 
   lsdb.processInterest(ndn::Name(), interest);
-  face->processEvents(ndn::time::milliseconds(1));
 
-  std::vector<ndn::Data> data = face->sentData;
+  advanceClocks(ndn::time::milliseconds(1), 10);
+
   std::string recvDataContent;
-  for (unsigned int i = 0; i < data.size(); ++i)
+  for (const ndn::Data& data : face.sentData)
   {
-    const ndn::Block& nameBlock = data[i].getContent();
-
+    const ndn::Block& nameBlock = data.getContent();
     std::string nameBlockContent(reinterpret_cast<char const*>(nameBlock.value()),
                                  nameBlock.value_size());
+
     recvDataContent += nameBlockContent;
   }
 
@@ -253,7 +260,7 @@
   //1800 is the default life time.
   NameLsa nlsa1(ndn::Name("/router1/1"), 12, testTimePoint, npl1);
 
-  Lsdb lsdb1(nlsr, g_scheduler);
+  Lsdb lsdb1(nlsr, m_scheduler);
 
   lsdb1.installNameLsa(nlsa1);
   lsdb1.writeNameLsdbLog();
diff --git a/tests/test-name-prefix-table.cpp b/tests/test-name-prefix-table.cpp
index 5322cb7..ceeb828 100644
--- a/tests/test-name-prefix-table.cpp
+++ b/tests/test-name-prefix-table.cpp
@@ -32,8 +32,8 @@
 {
 public:
   NamePrefixTableFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
-    , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+    : face(m_ioService, m_keyChain)
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , lsdb(nlsr.getLsdb())
     , npt(nlsr.getNamePrefixTable())
   {
@@ -41,7 +41,7 @@
   }
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
+  ndn::util::DummyClientFace face;
   Nlsr nlsr;
 
   Lsdb& lsdb;
@@ -63,10 +63,10 @@
 
   NamePrefixTable& npt = nlsr.getNamePrefixTable();
 
-  Adjacent thisRouter(conf.getRouterPrefix(), ndn::util::FaceUri("udp4://10.0.0.1"), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+  Adjacent thisRouter(conf.getRouterPrefix(), ndn::FaceUri("udp4://10.0.0.1"), 0, Adjacent::STATUS_ACTIVE, 0, 0);
 
   ndn::Name buptRouterName("/ndn/cn/edu/bupt/%C1.Router/bupthub");
-  Adjacent bupt(buptRouterName, ndn::util::FaceUri("udp4://10.0.0.2"), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+  Adjacent bupt(buptRouterName, ndn::FaceUri("udp4://10.0.0.2"), 0, Adjacent::STATUS_ACTIVE, 0, 0);
 
   // This router's Adjacency LSA
   nlsr.getAdjacencyList().insert(bupt);
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index fe30864..180c295 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -35,12 +35,18 @@
 {
 public:
   NlsrFixture()
-    : nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+    : nlsr(m_ioService, m_scheduler, m_face, m_keyChain)
     , lsdb(nlsr.getLsdb())
     , neighbors(nlsr.getAdjacencyList())
     , nSuccessCallbacks(0)
     , nFailureCallbacks(0)
   {
+    nlsr.getConfParameter().setNetwork("/ndn");
+    nlsr.getConfParameter().setSiteName("/site");
+    nlsr.getConfParameter().setRouterName("/%C1.Router/this-router");
+    nlsr.getConfParameter().buildRouterPrefix();
+
+    addIdentity(nlsr.getConfParameter().getRouterPrefix());
   }
 
   void
@@ -49,10 +55,10 @@
     ndn::Name dataName(sender);
     dataName.append("NLSR").append("INFO").append(receiver.wireEncode()).appendVersion();
 
-    std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(dataName);
+    ndn::Data data(dataName);
 
     nlsr.m_helloProtocol.onContentValidated(data);
- }
+  }
 
 public:
   Nlsr nlsr;
@@ -60,7 +66,6 @@
   AdjacencyList& neighbors;
   uint32_t nSuccessCallbacks;
   uint32_t nFailureCallbacks;
-
 };
 
 BOOST_FIXTURE_TEST_SUITE(TestNlsr, NlsrFixture)
@@ -68,20 +73,19 @@
 BOOST_AUTO_TEST_CASE(HyperbolicOn_ZeroCostNeighbors)
 {
   // Simulate loading configuration file
-  Adjacent neighborA("/ndn/neighborA", ndn::util::FaceUri("udp4://10.0.0.1"), 25,
+  Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"), 25,
                      Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborA);
 
-  Adjacent neighborB("/ndn/neighborB", ndn::util::FaceUri("udp4://10.0.0.2"), 10,
+  Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"), 10,
                      Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborB);
 
-  Adjacent neighborC("/ndn/neighborC", ndn::util::FaceUri("udp4://10.0.0.3"), 17,
+  Adjacent neighborC("/ndn/neighborC", ndn::FaceUri("udp4://10.0.0.3"), 17,
                      Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborC);
 
   nlsr.getConfParameter().setHyperbolicState(HYPERBOLIC_STATE_ON);
-  nlsr.getConfParameter().setNetwork(ndn::Name("/test"));
 
   nlsr.initialize();
 
@@ -94,15 +98,15 @@
 BOOST_AUTO_TEST_CASE(HyperbolicOff_LinkStateCost)
 {
   // Simulate loading configuration file
-  Adjacent neighborA("/ndn/neighborA", ndn::util::FaceUri("udp4://10.0.0.1"), 25,
+  Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"), 25,
                      Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborA);
 
-  Adjacent neighborB("/ndn/neighborB", ndn::util::FaceUri("udp4://10.0.0.2"), 10,
+  Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"), 10,
                      Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborB);
 
-  Adjacent neighborC("/ndn/neighborC", ndn::util::FaceUri("udp4://10.0.0.3"), 17,
+  Adjacent neighborC("/ndn/neighborC", ndn::FaceUri("udp4://10.0.0.3"), 17,
                      Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborC);
 
@@ -137,11 +141,13 @@
   // Setting constants for the unit test
   const uint32_t faceId = 1;
   const std::string faceUri = "udp4://10.0.0.1:6363";
-  Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(faceUri), 10,
+
+  Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(faceUri), 10,
                     Adjacent::STATUS_INACTIVE, 0, 0);
+
   BOOST_REQUIRE_EQUAL(nlsr.getAdjacencyList().insert(neighbor), 0);
 
-  this->advanceClocks(ndn::time::milliseconds(1));
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   // Build, sign, and send the Face Event
   ndn::nfd::FaceEventNotification event;
@@ -151,14 +157,14 @@
   std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
   data->setContent(event.wireEncode());
   nlsr.getKeyChain().sign(*data);
-  face->receive(*data);
+  m_face.receive(*data);
 
   // Move the clocks forward so that the Face processes the event.
-  this->advanceClocks(ndn::time::milliseconds(1));
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   // Need to explicitly provide a FaceUri object, because the
   // conversion will attempt to create Name objects.
-  auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(faceUri));
+  auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::FaceUri(faceUri));
   BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
   BOOST_CHECK_EQUAL(iterator->getFaceId(), faceId);
 }
@@ -169,8 +175,10 @@
   const uint32_t faceId = 1;
   const std::string eventUri = "udp4://10.0.0.1:6363";
   const std::string neighborUri = "udp4://10.0.0.2:6363";
-  Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(neighborUri), 10,
+
+  Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(neighborUri), 10,
                     Adjacent::STATUS_INACTIVE, 0, 0);
+
   nlsr.getAdjacencyList().insert(neighbor);
 
   // Build, sign, and send the Face Event
@@ -181,13 +189,13 @@
   std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
   data->setContent(event.wireEncode());
   nlsr.getKeyChain().sign(*data);
-  face->receive(*data);
+  m_face.receive(*data);
 
   // Move the clocks forward so that the Face processes the event.
-  this->advanceClocks(ndn::time::milliseconds(1));
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   // The Face URIs did not match, so this neighbor should be unconfigured.
-  auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(neighborUri));
+  auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::FaceUri(neighborUri));
   BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
   BOOST_CHECK_EQUAL(iterator->getFaceId(), 0);
 }
@@ -198,7 +206,8 @@
   const uint32_t eventFaceId = 1;
   const uint32_t neighborFaceId = 2;
   const std::string faceUri = "udp4://10.0.0.1:6363";
-  Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(faceUri), 10,
+
+  Adjacent neighbor("/ndn/neighborA", ndn::FaceUri(faceUri), 10,
                     Adjacent::STATUS_ACTIVE, 0, neighborFaceId);
   nlsr.getAdjacencyList().insert(neighbor);
 
@@ -210,29 +219,22 @@
   std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
   data->setContent(event.wireEncode());
   nlsr.getKeyChain().sign(*data);
-  face->receive(*data);
+  m_face.receive(*data);
 
   // Move the clocks forward so that the Face processes the event.
-  this->advanceClocks(ndn::time::milliseconds(1));
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   // Since the neighbor was already configured, this (simply erroneous) event should have no effect.
-  auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(faceUri));
+  auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::FaceUri(faceUri));
   BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
   BOOST_CHECK_EQUAL(iterator->getFaceId(), neighborFaceId);
 }
 
-BOOST_FIXTURE_TEST_CASE(FaceDestroyEvent, UnitTestTimeFixture)
+BOOST_AUTO_TEST_CASE(FaceDestroyEvent)
 {
-  std::shared_ptr<ndn::util::DummyClientFace> face =
-    std::make_shared<ndn::util::DummyClientFace>(g_ioService);
-  Nlsr nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain);
-  Lsdb& lsdb = nlsr.getLsdb();
-
   // Simulate loading configuration file
   ConfParameter& conf = nlsr.getConfParameter();
-  conf.setNetwork("/ndn");
-  conf.setSiteName("/site");
-  conf.setRouterName("/%C1.router/this-router");
+
   conf.setAdjLsaBuildInterval(0);
   conf.setRoutingCalcInterval(0);
 
@@ -241,13 +243,13 @@
   uint64_t destroyFaceId = 128;
 
   // Create a neighbor whose Face will be destroyed
-  Adjacent failNeighbor("/ndn/neighborA", ndn::util::FaceUri("udp4://10.0.0.1"), 10, Adjacent::STATUS_ACTIVE, 0,
-                        destroyFaceId);
+  Adjacent failNeighbor("/ndn/neighborA", ndn::FaceUri("udp4://10.0.0.1"),
+                        10, Adjacent::STATUS_ACTIVE, 0, destroyFaceId);
   neighbors.insert(failNeighbor);
 
   // Create an additional neighbor so an adjacency LSA can be built after the face is destroyed
-  Adjacent otherNeighbor("/ndn/neighborB", ndn::util::FaceUri("udp4://10.0.0.2"), 10,
-                         Adjacent::STATUS_ACTIVE, 0, 256);
+  Adjacent otherNeighbor("/ndn/neighborB", ndn::FaceUri("udp4://10.0.0.2"),
+                          10, Adjacent::STATUS_ACTIVE, 0, 256);
   neighbors.insert(otherNeighbor);
 
   nlsr.initialize();
@@ -257,10 +259,11 @@
 
   // Set up adjacency LSAs
   // This router
-  Adjacent thisRouter(conf.getRouterPrefix(), ndn::util::FaceUri("udp4://10.0.0.3"), 10,
-                      Adjacent::STATUS_ACTIVE, 0, 256);
+  Adjacent thisRouter(conf.getRouterPrefix(), ndn::FaceUri("udp4://10.0.0.3"),
+                      10, Adjacent::STATUS_ACTIVE, 0, 256);
 
-  AdjLsa ownAdjLsa(conf.getRouterPrefix(), 10, ndn::time::system_clock::now(), 1, neighbors);
+  AdjLsa ownAdjLsa(conf.getRouterPrefix(), 10,
+                   ndn::time::system_clock::now(), 1, neighbors);
   lsdb.installAdjLsa(ownAdjLsa);
 
   // Router that will fail
@@ -268,7 +271,8 @@
   failAdjacencies.insert(thisRouter);
 
   AdjLsa failAdjLsa("/ndn/neighborA", 10,
-                     ndn::time::system_clock::now() + ndn::time::seconds(3600), 1, failAdjacencies);
+                    ndn::time::system_clock::now() + ndn::time::seconds(3600),
+                    1, failAdjacencies);
 
   lsdb.installAdjLsa(failAdjLsa);
 
@@ -277,12 +281,13 @@
   otherAdjacencies.insert(thisRouter);
 
   AdjLsa otherAdjLsa("/ndn/neighborB", 10,
-                     ndn::time::system_clock::now() + ndn::time::seconds(3600), 1, otherAdjacencies);
+                     ndn::time::system_clock::now() + ndn::time::seconds(3600),
+                     1, otherAdjacencies);
 
   lsdb.installAdjLsa(otherAdjLsa);
 
   // Run the scheduler to build an adjacency LSA
-  this->advanceClocks(ndn::time::milliseconds(1));
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   // Make sure an adjacency LSA was built
   ndn::Name key = ndn::Name(nlsr.getConfParameter().getRouterPrefix())
@@ -307,10 +312,10 @@
   data->setContent(event.wireEncode());
   nlsr.getKeyChain().sign(*data);
 
-  face->receive(*data);
+  m_face.receive(*data);
 
   // Run the scheduler to build an adjacency LSA
-  this->advanceClocks(ndn::time::milliseconds(1));
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   Adjacent updatedNeighbor = neighbors.getAdjacent(failNeighbor.getName());
 
@@ -332,15 +337,16 @@
 BOOST_AUTO_TEST_CASE(GetCertificate)
 {
   // Create certificate
-  ndn::Name identity("/TestNLSR/identity");
-  identity.appendVersion();
+  ndn::Name identityName("/TestNLSR/identity");
+  identityName.appendVersion();
 
-  ndn::KeyChain keyChain;
-  keyChain.createIdentity(identity);
-  ndn::Name certName = keyChain.getDefaultCertificateNameForIdentity(identity);
-  std::shared_ptr<ndn::IdentityCertificate> certificate = keyChain.getCertificate(certName);
+  ndn::security::pib::Identity identity = nlsr.getKeyChain().
+                                               createIdentity(identityName);
 
-  const ndn::Name certKey = certificate->getName().getPrefix(-1);
+  ndn::security::v2::Certificate certificate =
+    identity.getDefaultKey().getDefaultCertificate();
+
+  const ndn::Name certKey = certificate.getKeyName();
 
   BOOST_CHECK(nlsr.getCertificate(certKey) == nullptr);
 
@@ -350,59 +356,44 @@
   BOOST_CHECK(nlsr.getCertificate(certKey) != nullptr);
 
   nlsr.getCertificateStore().clear();
-
-  // Certificate should be retrievable from the cache
-  nlsr.addCertificateToCache(certificate);
-  this->advanceClocks(ndn::time::milliseconds(10));
-
-  BOOST_CHECK(nlsr.getCertificate(certKey) != nullptr);
 }
 
 BOOST_AUTO_TEST_CASE(SetRouterCommandPrefix)
 {
-  // Simulate loading configuration file
-  ConfParameter& conf = nlsr.getConfParameter();
-  conf.setNetwork("/ndn");
-  conf.setSiteName("/site");
-  conf.setRouterName("/%C1.router/this-router");
-
   nlsr.initialize();
 
   BOOST_CHECK_EQUAL(nlsr.getLsdbDatasetHandler().getRouterNameCommandPrefix(),
-                    ndn::Name("/ndn/site/%C1.router/this-router/lsdb"));
+                    ndn::Name("/ndn/site/%C1.Router/this-router/lsdb"));
 }
 
 BOOST_AUTO_TEST_CASE(BuildAdjLsaAfterHelloResponse)
 {
   // Configure NLSR
   ConfParameter& conf = nlsr.getConfParameter();
-  conf.setNetwork("/ndn");
-  conf.setSiteName("/site");
-
-  ndn::Name routerName("/%C1.Router/this-router");
-  conf.setRouterName(routerName);
 
   conf.setAdjLsaBuildInterval(1);
 
   // Add neighbors
   // Router A
-  ndn::Name neighborAName("/ndn/site/%C1.router/routerA");
-  Adjacent neighborA(neighborAName, ndn::util::FaceUri("udp4://10.0.0.1"), 0,
-                     Adjacent::STATUS_INACTIVE, 0, 0);
+  ndn::Name neighborAName("/ndn/site/%C1.Router/routerA");
+  Adjacent neighborA(neighborAName, ndn::FaceUri("udp4://10.0.0.1"),
+                     0, Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborA);
 
   // Router B
-  ndn::Name neighborBName("/ndn/site/%C1.router/routerB");
-  Adjacent neighborB(neighborBName, ndn::util::FaceUri("udp4://10.0.0.1"), 0,
-                     Adjacent::STATUS_INACTIVE, 0, 0);
+  ndn::Name neighborBName("/ndn/site/%C1.Router/routerB");
+  Adjacent neighborB(neighborBName, ndn::FaceUri("udp4://10.0.0.1"),
+                     0, Adjacent::STATUS_INACTIVE, 0, 0);
+
   neighbors.insert(neighborB);
 
   nlsr.initialize();
-  this->advanceClocks(ndn::time::milliseconds(1));
+
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   // Receive HELLO response from Router A
   receiveHelloData(neighborAName, conf.getRouterPrefix());
-  this->advanceClocks(ndn::time::seconds(1));
+  this->advanceClocks(ndn::time::seconds(1), 10);
 
   ndn::Name lsaKey = ndn::Name(conf.getRouterPrefix()).append(std::to_string(Lsa::Type::ADJACENCY));
 
@@ -420,17 +411,17 @@
     adjacency.setInterestTimedOutNo(HELLO_RETRIES_DEFAULT);
   }
 
-  this->advanceClocks(ndn::time::seconds(1));
+  this->advanceClocks(ndn::time::seconds(1), 10);
 
-  // Adjacency LSA should have been removed since this router's adjacencies are INACTIVE
-  // and have timed out
+  // Adjacency LSA should have been removed since this router's adjacencies are
+  // INACTIVE and have timed out
   lsa = lsdb.findAdjLsa(lsaKey);
   BOOST_CHECK(lsa == nullptr);
 
   // Receive HELLO response from Router A and B
   receiveHelloData(neighborAName, conf.getRouterPrefix());
   receiveHelloData(neighborBName, conf.getRouterPrefix());
-  this->advanceClocks(ndn::time::seconds(1));
+  this->advanceClocks(ndn::time::seconds(1), 10);
 
   // Adjacency LSA should be built
   lsa = lsdb.findAdjLsa(lsaKey);
@@ -440,13 +431,13 @@
 
 BOOST_AUTO_TEST_CASE(CanonizeUris)
 {
-  ndn::Name neighborAName("/ndn/site/%C1.router/routerA");
-  ndn::util::FaceUri faceUriA("udp://10.0.0.1");
+  ndn::Name neighborAName("/ndn/site/%C1.Router/routerA");
+  ndn::FaceUri faceUriA("udp://10.0.0.1");
   Adjacent neighborA(neighborAName, faceUriA, 0, Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborA);
 
-  ndn::Name neighborBName("/ndn/site/%C1.router/routerB");
-  ndn::util::FaceUri faceUriB("udp://10.0.0.2");
+  ndn::Name neighborBName("/ndn/site/%C1.Router/routerB");
+  ndn::FaceUri faceUriB("udp://10.0.0.2");
   Adjacent neighborB(neighborBName, faceUriB, 0, Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborB);
 
@@ -467,20 +458,19 @@
                             },
                             finallyCallback);
   while (nCanonizationsLeft != 0) {
-    this->advanceClocks(ndn::time::milliseconds(1));
+    this->advanceClocks(ndn::time::milliseconds(1), 10);
   }
 
   BOOST_CHECK_EQUAL(nlsr.getAdjacencyList().getAdjacent(neighborAName).getFaceUri(),
-                    ndn::util::FaceUri("udp4://10.0.0.1:6363"));
+                    ndn::FaceUri("udp4://10.0.0.1:6363"));
 
   BOOST_CHECK_EQUAL(nlsr.getAdjacencyList().getAdjacent(neighborBName).getFaceUri(),
-                    ndn::util::FaceUri("udp4://10.0.0.2:6363"));
+                    ndn::FaceUri("udp4://10.0.0.2:6363"));
 }
 
 BOOST_AUTO_TEST_CASE(FaceDatasetFetchSuccess)
 {
   bool hasResult = false;
-  nlsr.m_validator.m_shouldValidate = false;
 
   nlsr.initializeFaces([&hasResult] (const std::vector<ndn::nfd::FaceStatus>& faces) {
       hasResult = true;
@@ -490,7 +480,7 @@
     },
     [] (uint32_t code, const std::string& reason) {});
 
-  this->advanceClocks(ndn::time::milliseconds(500));
+  this->advanceClocks(ndn::time::milliseconds(100), 5);
 
   ndn::nfd::FaceStatus payload1;
   payload1.setFaceId(25401);
@@ -498,22 +488,21 @@
   payload2.setFaceId(25402);
   this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
 
-  this->advanceClocks(ndn::time::milliseconds(500));
+  this->advanceClocks(ndn::time::milliseconds(100), 5);
   BOOST_CHECK(hasResult);
 }
 
 BOOST_AUTO_TEST_CASE(FaceDatasetFetchFailure)
 {
-  nlsr.m_validator.m_shouldValidate = false;
   nlsr.initializeFaces([](const std::vector<ndn::nfd::FaceStatus>& faces) {},
     [this](uint32_t code, const std::string& reason){
       this->nFailureCallbacks++;
     });
-  this->advanceClocks(ndn::time::milliseconds(500));
+  this->advanceClocks(ndn::time::milliseconds(100), 5);
 
   ndn::Name payload;
   this->sendDataset("/localhost/nfd/faces/list", payload);
-  this->advanceClocks(ndn::time::milliseconds(500));
+  this->advanceClocks(ndn::time::milliseconds(100), 5);
 
   BOOST_CHECK_EQUAL(nFailureCallbacks, 1);
   BOOST_CHECK_EQUAL(nSuccessCallbacks, 0);
@@ -521,12 +510,12 @@
 
 BOOST_AUTO_TEST_CASE(FaceDatasetProcess)
 {
-  Adjacent neighborA("/ndn/neighborA", ndn::util::FaceUri("udp4://192.168.0.100:6363"), 25,
-                     Adjacent::STATUS_INACTIVE, 0, 0);
+  Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://192.168.0.100:6363"),
+                     25, Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborA);
 
-  Adjacent neighborB("/ndn/neighborB", ndn::util::FaceUri("udp4://192.168.0.101:6363"), 10,
-                     Adjacent::STATUS_INACTIVE, 0, 0);
+  Adjacent neighborB("/ndn/neighborB", ndn::FaceUri("udp4://192.168.0.101:6363"),
+                     10, Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborB);
 
   ndn::nfd::FaceStatus payload1;
@@ -538,7 +527,6 @@
   std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload1, payload2};
 
   nlsr.processFaceDataset(faceStatuses);
-  this->advanceClocks(ndn::time::milliseconds(100));
 
   AdjacencyList adjList = nlsr.getAdjacencyList();
 
@@ -548,8 +536,7 @@
 
 BOOST_AUTO_TEST_CASE(UnconfiguredNeighbor)
 {
-  Adjacent neighborA("/ndn/neighborA", ndn::util::FaceUri("udp4://192.168.0.100:6363"), 25,
-                     Adjacent::STATUS_INACTIVE, 0, 0);
+  Adjacent neighborA("/ndn/neighborA", ndn::FaceUri("udp4://192.168.0.100:6363"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
   neighbors.insert(neighborA);
 
   ndn::nfd::FaceStatus payload;
@@ -558,7 +545,7 @@
   std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload};
 
   nlsr.processFaceDataset(faceStatuses);
-  this->advanceClocks(ndn::time::milliseconds(100));
+  this->advanceClocks(ndn::time::milliseconds(20), 5);
 
   AdjacencyList adjList = nlsr.getAdjacencyList();
 
@@ -584,7 +571,7 @@
   this->advanceClocks(defaultTimeout);
 
   // Check that we have one interest for face list in the sent interests.
-  for (const ndn::Interest& interest : face->sentInterests) {
+  for (const ndn::Interest& interest : m_face.sentInterests) {
     if (datasetPrefix.isPrefixOf(interest.getName())) {
       nNameMatches++;
     }
@@ -600,7 +587,7 @@
 
   // Check that we now have two interests
   nNameMatches = 0;
-  for (const ndn::Interest& interest : face->sentInterests) {
+  for (const ndn::Interest& interest : m_face.sentInterests) {
     if (datasetPrefix.isPrefixOf(interest.getName())) {
       nNameMatches++;
     }
diff --git a/tests/test-routing-table.cpp b/tests/test-routing-table.cpp
index 8bfcedb..b420f2f 100644
--- a/tests/test-routing-table.cpp
+++ b/tests/test-routing-table.cpp
@@ -21,8 +21,8 @@
  *
  **/
 
-#include "test-common.hpp"
 #include "route/routing-table.hpp"
+#include "test-common.hpp"
 #include "route/routing-table-entry.hpp"
 #include "route/nexthop.hpp"
 #include <boost/test/unit_test.hpp>
@@ -34,7 +34,7 @@
 
 BOOST_AUTO_TEST_CASE(RoutingTableAddNextHop)
 {
-  RoutingTable rt1(g_scheduler);
+  RoutingTable rt1(m_scheduler);
 
   NextHop nh1;
 
diff --git a/tests/test-statistics.cpp b/tests/test-statistics.cpp
index b148cb2..90a2a67 100644
--- a/tests/test-statistics.cpp
+++ b/tests/test-statistics.cpp
@@ -30,12 +30,12 @@
 namespace nlsr {
 namespace test {
 
-class StatisticsFixture : public BaseFixture
+class StatisticsFixture : public UnitTestTimeFixture
 {
 public:
   StatisticsFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
-    , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+    : face(m_ioService, m_keyChain)
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , lsdb(nlsr.getLsdb())
     , hello(nlsr.m_helloProtocol)
     , conf(nlsr.getConfParameter())
@@ -43,13 +43,15 @@
   {
     conf.setNetwork("/ndn");
     conf.setSiteName("/site");
-    conf.setRouterName("/%C1.router/this-router");
+    conf.setRouterName("/%C1.Router/this-router");
     conf.buildRouterPrefix();
 
+    addIdentity(conf.getRouterPrefix());
+
     nlsr.initialize();
 
-    face->processEvents(ndn::time::milliseconds(1));
-    face->sentInterests.clear();
+    this->advanceClocks(ndn::time::milliseconds(1), 10);
+    face.sentInterests.clear();
   }
 
   /*!
@@ -77,7 +79,7 @@
 
     ndn::Name interestName = ndn::Name(ndn::Name(interestPrefix + lsaType).appendNumber(seqNo));
     lsdb.processInterest(ndn::Name(), ndn::Interest(interestName));
-    face->processEvents(ndn::time::milliseconds(1));
+    this->advanceClocks(ndn::time::milliseconds(1), 10);
 
     BOOST_CHECK_EQUAL(collector.getStatistics().get(receivedInterestType), rcvBefore + 1);
     BOOST_CHECK_EQUAL(collector.getStatistics().get(sentDataType), sentBefore + 1);
@@ -104,13 +106,13 @@
 
     lsdb.expressInterest(ndn::Name(prefix + lsaType).appendNumber(seqNo), 0,
                          ndn::time::steady_clock::TimePoint::min());
-    face->processEvents(ndn::time::milliseconds(1));
+    this->advanceClocks(ndn::time::milliseconds(1), 10);
 
     BOOST_CHECK_EQUAL(collector.getStatistics().get(statsType), sentBefore + 1);
   }
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
+  ndn::util::DummyClientFace face;
   Nlsr nlsr;
 
   Lsdb& lsdb;
@@ -143,48 +145,44 @@
   BOOST_CHECK_EQUAL(stats.get(Statistics::PacketType::SENT_HELLO_INTEREST), 0);
 }
 
-
 /*
  * This tests hello interests and hello data statistical collection by constructing an adjacency lsa
  * and calling functions that trigger the sending and receiving hello of interests/data.
  */
 BOOST_AUTO_TEST_CASE(SendHelloInterest)
 {
-  nlsr.initialize();
-
-  face->processEvents(ndn::time::milliseconds(1));
-  face->sentInterests.clear();
-
-  Adjacent other("/ndn/router/other", ndn::util::FaceUri("udp4://other"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
+  Adjacent other("/ndn/router/other", ndn::FaceUri("udp4://other"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
 
   // This router's Adjacency LSA
   nlsr.getAdjacencyList().insert(other);
 
-  ndn::Name name(conf.getRouterPrefix());
-  name.append("NLSR");
-  name.append("INFO");
-  name.append(other.getName().wireEncode());
+  ndn::Name otherName(other.getName());
+  otherName.append("NLSR");
+  otherName.append("INFO");
+  otherName.append(conf.getRouterPrefix().wireEncode());
 
-  hello.expressInterest(name, 1);
-  face->processEvents(ndn::time::milliseconds(1));
+  hello.expressInterest(otherName, 1);
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_HELLO_INTEREST), 1);
 
-  ndn::Interest interest(name);
+  ndn::Name thisName(conf.getRouterPrefix());
+  thisName.append("NLSR");
+  thisName.append("INFO");
+  thisName.append(other.getName().wireEncode());
+
+  ndn::Interest interest(thisName);
   hello.processInterest(ndn::Name(), interest);
 
-  face->processEvents(ndn::time::milliseconds(1));
+  this->advanceClocks(ndn::time::milliseconds(1), 10);
 
   BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_HELLO_INTEREST), 1);
   BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::SENT_HELLO_DATA), 1);
 
   // Receive Hello Data
-  ndn::Name dataName = other.getName();
-  dataName.append("NLSR");
-  dataName.append("INFO");
-  dataName.append(conf.getRouterPrefix().wireEncode());
+  ndn::Name dataName = otherName;
 
-  std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>(dataName);
+  ndn::Data data(dataName);
   hello.onContentValidated(data);
 
   BOOST_CHECK_EQUAL(collector.getStatistics().get(Statistics::PacketType::RCV_HELLO_DATA), 1);
diff --git a/tests/test-sync-logic-handler.cpp b/tests/test-sync-logic-handler.cpp
index e660a5d..f696d42 100644
--- a/tests/test-sync-logic-handler.cpp
+++ b/tests/test-sync-logic-handler.cpp
@@ -33,12 +33,12 @@
 
 using std::shared_ptr;
 
-class SyncLogicFixture : public BaseFixture
+class SyncLogicFixture : public UnitTestTimeFixture
 {
 public:
   SyncLogicFixture()
-    : face(std::make_shared<ndn::util::DummyClientFace>())
-    , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+    : face(m_ioService, m_keyChain)
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , testIsLsaNew([] (const ndn::Name& name, const Lsa::Type& lsaType,
                        const uint64_t sequenceNumber) {
                      return true;
@@ -57,6 +57,9 @@
     conf.setSiteName(CONFIG_SITE);
     conf.setRouterName(CONFIG_ROUTER_NAME);
     conf.buildRouterPrefix();
+
+    addIdentity(conf.getRouterPrefix());
+
     INIT_LOGGERS("/tmp", "TRACE");
   }
 
@@ -68,16 +71,16 @@
     std::vector<chronosync::MissingDataInfo> updates;
     updates.push_back(info);
 
-    face->processEvents(ndn::time::milliseconds(1));
-    face->sentInterests.clear();
+    this->advanceClocks(ndn::time::milliseconds(1), 10);
+    face.sentInterests.clear();
 
     p_sync.onChronoSyncUpdate(updates);
 
-    face->processEvents(ndn::time::milliseconds(1));
+    this->advanceClocks(ndn::time::milliseconds(1), 10);
   }
 
 public:
-  std::shared_ptr<ndn::util::DummyClientFace> face;
+  ndn::util::DummyClientFace face;
   Nlsr nlsr;
   ConfParameter conf;
   SyncLogicHandler::IsLsaNew testIsLsaNew;
@@ -98,7 +101,7 @@
  */
 BOOST_AUTO_TEST_CASE(UpdateForOtherLS)
 {
-  SyncLogicHandler sync{std::ref(*face), testIsLsaNew, conf};
+  SyncLogicHandler sync{face, testIsLsaNew, conf};
   sync.createSyncSocket(conf.getChronosyncPrefix());
 
   std::vector<Lsa::Type> lsaTypes = {Lsa::Type::NAME, Lsa::Type::ADJACENCY};
@@ -128,7 +131,7 @@
 {
   conf.setHyperbolicState(HYPERBOLIC_STATE_ON);
 
-  SyncLogicHandler sync{std::ref(*face), testIsLsaNew, conf};
+  SyncLogicHandler sync{face, testIsLsaNew, conf};
   sync.createSyncSocket(conf.getChronosyncPrefix());
 
   uint64_t syncSeqNo = 1;
@@ -156,7 +159,7 @@
 {
   conf.setHyperbolicState(HYPERBOLIC_STATE_DRY_RUN);
 
-  SyncLogicHandler sync{std::ref(*face), testIsLsaNew, conf};
+  SyncLogicHandler sync{face, testIsLsaNew, conf};
   sync.createSyncSocket(conf.getChronosyncPrefix());
 
   for (const Lsa::Type& lsaType : lsaTypes) {
@@ -183,7 +186,7 @@
 {
   const uint64_t sequenceNumber = 1;
 
-  SyncLogicHandler sync{std::ref(*face), testIsLsaNew, conf};
+  SyncLogicHandler sync{face, testIsLsaNew, conf};
   sync.createSyncSocket(conf.getChronosyncPrefix());
 
   for (const Lsa::Type& lsaType : lsaTypes) {
@@ -209,7 +212,7 @@
 {
   const uint64_t sequenceNumber = 1;
 
-  SyncLogicHandler sync{std::ref(*face), testIsLsaNew, conf};
+  SyncLogicHandler sync{face, testIsLsaNew, conf};
   sync.createSyncSocket(conf.getChronosyncPrefix());
 
   for (const Lsa::Type& lsaType : lsaTypes) {
@@ -237,7 +240,7 @@
   };
 
   const uint64_t sequenceNumber = 1;
-  SyncLogicHandler sync{std::ref(*face), testLsaAlwaysFalse, conf};
+  SyncLogicHandler sync{face, testLsaAlwaysFalse, conf};
   sync.createSyncSocket(conf.getChronosyncPrefix());
     ndn::util::signal::ScopedConnection connection = sync.onNewLsa->connect(
       [& ,this] (const ndn::Name& routerName, const uint64_t& sequenceNumber) {
@@ -258,7 +261,7 @@
 BOOST_AUTO_TEST_CASE(UpdatePrefix)
 {
 
-  SyncLogicHandler sync{std::ref(*face), testIsLsaNew, conf};
+  SyncLogicHandler sync{face, testIsLsaNew, conf};
 
   ndn::Name expectedPrefix = nlsr.getConfParameter().getLsaPrefix();
   expectedPrefix.append(CONFIG_SITE);
diff --git a/tests/update/test-advertise-crash.cpp b/tests/update/test-advertise-crash.cpp
index 4f59c49..db9dfe6 100644
--- a/tests/update/test-advertise-crash.cpp
+++ b/tests/update/test-advertise-crash.cpp
@@ -30,14 +30,14 @@
 {
 public:
   AdvertiseCrashFixture()
-    : face(g_ioService, keyChain, {true, true})
-    , nlsr(g_ioService, g_scheduler, face, g_keyChain)
+    : face(m_ioService, m_keyChain, {true, true})
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , namePrefixList(nlsr.getNamePrefixList())
     , updatePrefixUpdateProcessor(nlsr.getPrefixUpdateProcessor())
   {
     // Add an adjacency to nlsr
     Adjacent adj("/ndn/edu/test-site-2/%C1.Router/test",
-                 ndn::util::FaceUri("udp://1.0.0.2"), 10, Adjacent::STATUS_INACTIVE, 0, 0);
+                 ndn::FaceUri("udp://1.0.0.2"), 10, Adjacent::STATUS_INACTIVE, 0, 0);
     nlsr.getAdjacencyList().insert(adj);
 
     // Create a face dataset response with the face having the same uri as
@@ -50,6 +50,9 @@
 
     // Set the network so the LSA prefix is constructed
     nlsr.getConfParameter().setNetwork("/ndn");
+    nlsr.getConfParameter().setRouterName(ndn::Name("/This/router"));
+
+    addIdentity(ndn::Name("/ndn/This/router"));
 
     // So that NLSR starts listening on prefixes
     nlsr.initialize();
@@ -59,14 +62,13 @@
     // in fib.cpp if an operation is done on non-existent faceUri
     nlsr.processFaceDataset(faces);
 
-    this->advanceClocks(ndn::time::milliseconds(1));
+    this->advanceClocks(ndn::time::milliseconds(1), 10);
 
     face.sentInterests.clear();
   }
 
 public:
   ndn::util::DummyClientFace face;
-  ndn::KeyChain keyChain;
 
   Nlsr nlsr;
   NamePrefixList& namePrefixList;
@@ -89,7 +91,7 @@
   std::shared_ptr<ndn::Interest> advertiseInterest = std::make_shared<ndn::Interest>(advertiseCommand);
 
   face.receive(*advertiseInterest);
-  this->advanceClocks(ndn::time::milliseconds(10));
+  this->advanceClocks(ndn::time::milliseconds(10), 10);
 }
 
 } // namespace test
diff --git a/tests/update/test-nfd-rib-command-processor.cpp b/tests/update/test-nfd-rib-command-processor.cpp
index 53c77a1..2a78171 100644
--- a/tests/update/test-nfd-rib-command-processor.cpp
+++ b/tests/update/test-nfd-rib-command-processor.cpp
@@ -39,13 +39,16 @@
 {
 public:
   NfdRibCommandProcessorFixture()
-    : face(g_ioService, keyChain, {true, true})
-    , nlsr(g_ioService, g_scheduler, face, g_keyChain)
+    : face(m_ioService, m_keyChain, {true, true})
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , namePrefixes(nlsr.getNamePrefixList())
     , processor(nlsr.getNfdRibCommandProcessor())
   {
     // Set the network so the LSA prefix is constructed
     nlsr.getConfParameter().setNetwork("/ndn");
+    nlsr.getConfParameter().setRouterName(ndn::Name("/This/router"));
+
+    addIdentity(ndn::Name("/ndn/This/router"));
 
     // Initialize NLSR so a sync socket is created
     nlsr.initialize();
@@ -54,7 +57,7 @@
     // be the same value as what ChronoSync uses in setting the sessionName
     sessionTime.appendNumber(ndn::time::toUnixTimestamp(ndn::time::system_clock::now()).count());
 
-    this->advanceClocks(ndn::time::milliseconds(10));
+    this->advanceClocks(ndn::time::milliseconds(10), 10);
     face.sentInterests.clear();
 
     nameLsaSeqNoBeforeInterest = nlsr.getLsdb().getSequencingManager().getNameLsaSeq();
@@ -74,7 +77,7 @@
     // Need to send an interest now since ChronoSync
     // no longer does face->put(*data) in publishData.
     // Instead it does it in onInterest
-    ndn::Name lsaInterestName("/localhop/ndn/NLSR/LSA");
+    ndn::Name lsaInterestName("/localhop/ndn/NLSR/LSA/This/router");
     lsaInterestName.append(std::to_string(Lsa::Type::NAME));
 
     // The part after LSA is Chronosync getSession
@@ -83,13 +86,14 @@
     shared_ptr<ndn::Interest> lsaInterest = make_shared<ndn::Interest>(lsaInterestName);
 
     face.receive(*lsaInterest);
-    this->advanceClocks(ndn::time::milliseconds(10));
+    this->advanceClocks(ndn::time::milliseconds(10), 10);
   }
 
   bool
   wasRoutingUpdatePublished()
   {
     sendInterestForPublishedData();
+
     const ndn::Name& lsaPrefix = nlsr.getConfParameter().getLsaPrefix();
 
     const auto& it = std::find_if(face.sentData.begin(), face.sentData.end(),
@@ -102,7 +106,6 @@
 
 public:
   ndn::util::DummyClientFace face;
-  ndn::KeyChain keyChain;
 
   Nlsr nlsr;
   NamePrefixList& namePrefixes;
@@ -148,7 +151,7 @@
     .wireEncode()), 0);
 
   face.receive(*command);
-  this->advanceClocks(ndn::time::milliseconds(10));
+  this->advanceClocks(ndn::time::milliseconds(10), 10);
 
   BOOST_CHECK_EQUAL(namePrefixes.getNames().size(), 1);
   std::list<ndn::Name> names = namePrefixes.getNames();
@@ -173,7 +176,7 @@
     .wireEncode()), 0);
 
   face.receive(ndn::Interest(name));
-  this->advanceClocks(ndn::time::milliseconds(10));
+  this->advanceClocks(ndn::time::milliseconds(10), 10);
 
   BOOST_CHECK_EQUAL(namePrefixes.getNames().size(), 0);
   BOOST_CHECK(wasRoutingUpdatePublished());
@@ -190,7 +193,7 @@
     .wireEncode()), 0);
 
   face.receive(ndn::Interest(name));
-  this->advanceClocks(ndn::time::milliseconds(10));
+  this->advanceClocks(ndn::time::milliseconds(10), 10);
 
   BOOST_CHECK_EQUAL(namePrefixes.getNames().size(), 0);
 
diff --git a/tests/update/test-prefix-update-processor.cpp b/tests/update/test-prefix-update-processor.cpp
index 62ec8f6..5bb61f1 100644
--- a/tests/update/test-prefix-update-processor.cpp
+++ b/tests/update/test-prefix-update-processor.cpp
@@ -29,7 +29,11 @@
 #include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
 #include <ndn-cxx/mgmt/nfd/control-response.hpp>
 #include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/security/pib/identity.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
+#include <ndn-cxx/security/command-interest-signer.hpp>
 #include <ndn-cxx/util/dummy-client-face.hpp>
+#include <ndn-cxx/lp/tags.hpp>
 
 #include <boost/filesystem.hpp>
 
@@ -43,74 +47,78 @@
 {
 public:
   PrefixUpdateFixture()
-    : face(g_ioService, keyChain, {true, true})
-    , siteIdentity(ndn::Name("/ndn/edu/test-site").appendVersion())
-    , opIdentity(ndn::Name(siteIdentity).append(ndn::Name("%C1.Operator")).appendVersion())
-    , nlsr(g_ioService, g_scheduler, face, g_keyChain)
-    , keyPrefix(("/ndn/broadcast"))
+    : face(m_ioService, m_keyChain, {true, true})
+    , siteIdentityName(ndn::Name("/edu/test-site"))
+    , opIdentityName(ndn::Name("/edu/test-site").append(ndn::Name("%C1.Operator")))
+    , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , namePrefixList(nlsr.getNamePrefixList())
     , updatePrefixUpdateProcessor(nlsr.getPrefixUpdateProcessor())
     , SITE_CERT_PATH(boost::filesystem::current_path() / std::string("site.cert"))
   {
-    createSiteCert();
-    BOOST_REQUIRE(siteCert != nullptr);
+    // Site cert
+    siteIdentity = addIdentity(siteIdentityName);
+    saveCertificate(siteIdentity, SITE_CERT_PATH.string());
 
-    createOperatorCert();
-    BOOST_REQUIRE(opCert != nullptr);
+    // Operator cert
+    opIdentity = addSubCertificate(opIdentityName, siteIdentity);
 
-    const std::string CONFIG =
-      "rule\n"
-      "{\n"
-      "  id \"NLSR ControlCommand Rule\"\n"
-      "  for interest\n"
-      "  filter\n"
-      "  {\n"
-      "    type name\n"
-      "    regex ^<localhost><nlsr><prefix-update>[<advertise><withdraw>]<>$\n"
-      "  }\n"
-      "  checker\n"
-      "  {\n"
-      "    type customized\n"
-      "    sig-type rsa-sha256\n"
-      "    key-locator\n"
-      "    {\n"
-      "      type name\n"
-      "      regex ^([^<KEY><%C1.Operator>]*)<%C1.Operator>[^<KEY>]*<KEY><ksk-.*><ID-CERT>$\n"
-      "    }\n"
-      "  }\n"
-      "}\n"
-      "rule\n"
-      "{\n"
-      "  id \"NLSR Hierarchy Rule\"\n"
-      "  for data\n"
-      "  filter\n"
-      "  {\n"
-      "    type name\n"
-      "    regex ^[^<KEY>]*<KEY><ksk-.*><ID-CERT><>$\n"
-      "  }\n"
-      "  checker\n"
-      "  {\n"
-      "    type hierarchical\n"
-      "    sig-type rsa-sha256\n"
-      "  }\n"
-      "}\n"
-      "trust-anchor\n"
-      "{\n"
-      " type file\n"
-      " file-name \"site.cert\"\n"
-      "}\n";
+    const std::string CONFIG = R"CONF(
+        rule
+        {
+          id "NLSR ControlCommand Rule"
+          for interest
+          filter
+          {
+            type name
+            regex ^(<localhost><nlsr>)<prefix-update>[<advertise><withdraw>]<><><>$
+          }
+          checker
+          {
+            type customized
+            sig-type rsa-sha256
+            key-locator
+            {
+              type name
+              regex ^<>*<KEY><>$
+            }
+          }
+        }
+        rule
+        {
+          id "NLSR Hierarchy Rule"
+          for data
+          filter
+          {
+            type name
+            regex ^[^<KEY>]*<KEY><><><>$
+          }
+          checker
+          {
+            type hierarchical
+            sig-type rsa-sha256
+          }
+        }
+        trust-anchor
+        {
+         type file
+         file-name "site.cert"
+        }
+    )CONF";
 
     const boost::filesystem::path CONFIG_PATH =
       (boost::filesystem::current_path() / std::string("unit-test.conf"));
 
     updatePrefixUpdateProcessor.getValidator().load(CONFIG, CONFIG_PATH.native());
 
-    // Insert certs after the validator is loaded since ValidatorConfig::load() clears
-    // the certificate cache
-    nlsr.addCertificateToCache(opCert);
+    nlsr.loadCertToPublish(opIdentity.getDefaultKey().getDefaultCertificate());
 
     // Set the network so the LSA prefix is constructed
     nlsr.getConfParameter().setNetwork("/ndn");
+    nlsr.getConfParameter().setSiteName("/edu/test-site");
+    nlsr.getConfParameter().setRouterName("/%C1.Router/this-router");
+    nlsr.getConfParameter().buildRouterPrefix();
+
+    addIdentity(ndn::Name("/ndn/edu/test-site/%C1.Router/this-router"));
 
     // Initialize NLSR so a sync socket is created
     nlsr.initialize();
@@ -124,45 +132,14 @@
     face.sentInterests.clear();
   }
 
-  void
-  createSiteCert()
+  void sendInterestForPublishedData()
   {
-    // Site cert
-    keyChain.createIdentity(siteIdentity);
-    siteCertName = keyChain.getDefaultCertificateNameForIdentity(siteIdentity);
-    siteCert = keyChain.getCertificate(siteCertName);
-
-    ndn::io::save(*siteCert, SITE_CERT_PATH.string());
-  }
-
-  void
-  createOperatorCert()
-  {
-    // Operator cert
-    ndn::Name keyName = keyChain.generateRsaKeyPairAsDefault(opIdentity, true);
-
-    opCert = std::make_shared<ndn::IdentityCertificate>();
-    std::shared_ptr<ndn::PublicKey> pubKey = keyChain.getPublicKey(keyName);
-    opCertName = keyName.getPrefix(-1);
-    opCertName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
-    opCert->setName(opCertName);
-    opCert->setNotBefore(time::system_clock::now() - time::days(1));
-    opCert->setNotAfter(time::system_clock::now() + time::days(1));
-    opCert->setPublicKeyInfo(*pubKey);
-    opCert->addSubjectDescription(ndn::security::v1::CertificateSubjectDescription(ndn::oid::ATTRIBUTE_NAME,
-                                                                                   keyName.toUri()));
-    opCert->encode();
-
-    keyChain.signByIdentity(*opCert, siteIdentity);
-
-    keyChain.addCertificateAsIdentityDefault(*opCert);
-  }
-
-  void sendInterestForPublishedData() {
     // Need to send an interest now since ChronoSync
     // no longer does face->put(*data) in publishData.
     // Instead it does it in onInterest
-    ndn::Name lsaInterestName("/localhop/ndn/NLSR/LSA");
+    ndn::Name lsaInterestName = nlsr.getConfParameter().getLsaPrefix();
+    lsaInterestName.append(nlsr.getConfParameter().getSiteName());
+    lsaInterestName.append(nlsr.getConfParameter().getRouterName());
     lsaInterestName.append(std::to_string(Lsa::Type::NAME));
 
     // The part after LSA is Chronosync getSession
@@ -172,7 +149,7 @@
     std::shared_ptr<Interest> lsaInterest = std::make_shared<Interest>(lsaInterestName);
 
     face.receive(*lsaInterest);
-    this->advanceClocks(ndn::time::milliseconds(10));
+    this->advanceClocks(ndn::time::milliseconds(100));
   }
 
   bool
@@ -185,7 +162,8 @@
     const auto& it = std::find_if(face.sentData.begin(), face.sentData.end(),
       [lsaPrefix] (const ndn::Data& data) {
         return lsaPrefix.isPrefixOf(data.getName());
-      });
+      }
+    );
 
     return (it != face.sentData.end());
   }
@@ -204,28 +182,16 @@
     BOOST_CHECK_EQUAL(response.getCode(), expectedCode);
   }
 
-  ~PrefixUpdateFixture()
-  {
-    keyChain.deleteIdentity(siteIdentity);
-    keyChain.deleteIdentity(opIdentity);
-
-    boost::filesystem::remove(SITE_CERT_PATH);
-  }
-
 public:
   ndn::util::DummyClientFace face;
-  ndn::KeyChain keyChain;
 
-  ndn::Name siteIdentity;
-  ndn::Name siteCertName;
-  std::shared_ptr<IdentityCertificate> siteCert;
+  ndn::Name siteIdentityName;
+  ndn::security::pib::Identity siteIdentity;
 
-  ndn::Name opIdentity;
-  ndn::Name opCertName;
-  std::shared_ptr<IdentityCertificate> opCert;
+  ndn::Name opIdentityName;
+  ndn::security::pib::Identity opIdentity;
 
   Nlsr nlsr;
-  ndn::Name keyPrefix;
   NamePrefixList& namePrefixList;
   PrefixUpdateProcessor& updatePrefixUpdateProcessor;
 
@@ -238,16 +204,29 @@
 BOOST_AUTO_TEST_CASE(Basic)
 {
   uint64_t nameLsaSeqNoBeforeInterest = nlsr.getLsdb().getSequencingManager().getNameLsaSeq();
-  // Advertise
+
   ndn::nfd::ControlParameters parameters;
   parameters.setName("/prefix/to/advertise/");
+
+  // Control Command format: /<prefix>/<management-module>/<command-verb>/<control-parameters>
+  // /<timestamp>/<random-value>/<signed-interests-components>
+
+  // Advertise
   ndn::Name advertiseCommand("/localhost/nlsr/prefix-update/advertise");
+
+  // append /<control-parameters>
   advertiseCommand.append(parameters.wireEncode());
 
-  std::shared_ptr<Interest> advertiseInterest = std::make_shared<Interest>(advertiseCommand);
-  keyChain.signByIdentity(*advertiseInterest, opIdentity);
+  ndn::security::CommandInterestSigner cis(m_keyChain);
 
-  face.receive(*advertiseInterest);
+  // CommandInterestSigner::makeCommandInterest() will append the last
+  // three components: (<timestamp>/<random-value>/<signed-interests-components>)
+  ndn::Interest advertiseInterest =
+    cis.makeCommandInterest(advertiseCommand,
+                            ndn::security::signingByIdentity(opIdentity));
+
+  face.receive(advertiseInterest);
+
   this->advanceClocks(ndn::time::milliseconds(10));
 
   NamePrefixList& namePrefixList = nlsr.getNamePrefixList();
@@ -261,14 +240,15 @@
   face.sentData.clear();
   nameLsaSeqNoBeforeInterest = nlsr.getLsdb().getSequencingManager().getNameLsaSeq();
 
-  // Withdraw
+  //Withdraw
   ndn::Name withdrawCommand("/localhost/nlsr/prefix-update/withdraw");
   withdrawCommand.append(parameters.wireEncode());
 
-  std::shared_ptr<Interest> withdrawInterest = std::make_shared<Interest>(withdrawCommand);
-  keyChain.signByIdentity(*withdrawInterest, opIdentity);
+  ndn::Interest withdrawInterest
+    = cis.makeCommandInterest(withdrawCommand,
+                              ndn::security::signingByIdentity(opIdentity));
 
-  face.receive(*withdrawInterest);
+  face.receive(withdrawInterest);
   this->advanceClocks(ndn::time::milliseconds(10));
 
   BOOST_CHECK_EQUAL(namePrefixList.size(), 0);
diff --git a/tests/wscript b/tests/wscript
index b7b1933..a943f1e 100644
--- a/tests/wscript
+++ b/tests/wscript
@@ -1,8 +1,8 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 """
-Copyright (c) 2014-2016,  The University of Memphis
-                          Regents of the University of California,
+Copyright (c) 2014-2017,  The University of Memphis
+                          Regents of the University of California
 
 This file is part of NLSR (Named-data Link State Routing).
 See AUTHORS.md for complete list of NLSR authors and contributors.
@@ -22,23 +22,23 @@
 top = '..'
 
 def build(bld):
-    # Unit tests
-    if bld.env['WITH_TESTS']:
-        unit_test_main = bld(
-            target='unit-tests-main',
-            name='unit-tests-main',
-            features='cxx',
-            source=bld.path.ant_glob(['**/*.cpp']),
-            use='nlsr-objects',
-          )
+    if not bld.env['WITH_TESTS']:
+        return
 
+    bld(
+        features='cxx',
+        name='unit-tests-main',
+        target='unit-tests-main',
+        source='main.cpp',
+        defines=['BOOST_TEST_MODULE=NLSR Unit Tests'],
+        use='nlsr-objects'
+    )
 
-        # nlsr tests
-        unit_tests_nlsr = bld.program(
-            target='../unit-tests-nlsr',
-            features='cxx cxxprogram',
-            source=bld.path.ant_glob(['nlsr/**/*.cpp']),
-            use='nlsr-objects unit-tests-main',
-            includes='.',
-            install_path=None,
-          )
+    bld.program(
+        target='../unit-tests-nlsr',
+        features='cxx cxxprogram',
+        source=bld.path.ant_glob(['**/*.cpp'], excl=['main.cpp']),
+        use='nlsr-objects unit-tests-main',
+        install_path=None,
+        # defines='TEST_CONFIG_PATH=\"%s/conf-test\"' %(bld.bldnode)
+    )
diff --git a/tools/nlsrc.cpp b/tools/nlsrc.cpp
index 7612a3e..103fa26 100644
--- a/tools/nlsrc.cpp
+++ b/tools/nlsrc.cpp
@@ -31,6 +31,8 @@
 #include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
 #include <ndn-cxx/mgmt/nfd/control-response.hpp>
 #include <ndn-cxx/util/segment-fetcher.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/security/command-interest-signer.hpp>
 
 #include <iostream>
 
@@ -150,12 +152,18 @@
 
   ndn::Name commandName = NAME_UPDATE_PREFIX;
   commandName.append(verb);
+  commandName.append(parameters.wireEncode());
 
-  ndn::Interest interest(commandName.append(parameters.wireEncode()));
-  interest.setMustBeFresh(true);
-  m_keyChain.sign(interest);
+  ndn::security::CommandInterestSigner cis(m_keyChain);
 
-  m_face.expressInterest(interest,
+  ndn::Interest commandInterest =
+    cis.makeCommandInterest(commandName,
+                            ndn::security::signingByIdentity(m_keyChain.getPib().
+                                                             getDefaultIdentity()));
+
+  commandInterest.setMustBeFresh(true);
+
+  m_face.expressInterest(commandInterest,
                          std::bind(&Nlsrc::onControlResponse, this, info, _2),
                          std::bind(&Nlsrc::onTimeout, this, ERROR_CODE_TIMEOUT, "Nack"),
                          std::bind(&Nlsrc::onTimeout, this, ERROR_CODE_TIMEOUT, "Timeout"));
diff --git a/tools/nlsrc.hpp b/tools/nlsrc.hpp
index be6c8db..3dd44d6 100644
--- a/tools/nlsrc.hpp
+++ b/tools/nlsrc.hpp
@@ -147,7 +147,7 @@
 private:
   ndn::KeyChain m_keyChain;
   ndn::Face& m_face;
-  ndn::ValidatorNull m_validator;
+  ndn::security::ValidatorNull m_validator;
 
   std::deque<std::function<void()>> m_fetchSteps;
 
diff --git a/wscript b/wscript
index f8471ef..f599297 100644
--- a/wscript
+++ b/wscript
@@ -126,7 +126,6 @@
 
     if bld.env['WITH_TESTS']:
         bld.recurse('tests')
-        bld.recurse('tests-integrated')
 
     if bld.env['SPHINX_BUILD']:
         bld(features="sphinx",