tests: sync common testing infrastructure with ndn-cxx

Change-Id: I1e5cdcda8f6d3d9f9addc7a9f17359aedef9db7e
diff --git a/tests/clock-fixture.cpp b/tests/clock-fixture.cpp
new file mode 100644
index 0000000..b3b4ac7
--- /dev/null
+++ b/tests/clock-fixture.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2022,  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 "tests/clock-fixture.hpp"
+
+namespace nlsr {
+namespace test {
+
+ClockFixture::ClockFixture()
+  : m_steadyClock(std::make_shared<time::UnitTestSteadyClock>())
+  , m_systemClock(std::make_shared<time::UnitTestSystemClock>())
+{
+  time::setCustomClocks(m_steadyClock, m_systemClock);
+}
+
+ClockFixture::~ClockFixture()
+{
+  time::setCustomClocks(nullptr, nullptr);
+}
+
+void
+ClockFixture::advanceClocks(time::nanoseconds tick, time::nanoseconds total)
+{
+  BOOST_ASSERT(tick > time::nanoseconds::zero());
+  BOOST_ASSERT(total >= time::nanoseconds::zero());
+
+  while (total > time::nanoseconds::zero()) {
+    auto t = std::min(tick, total);
+    m_steadyClock->advance(t);
+    m_systemClock->advance(t);
+    total -= t;
+
+    afterTick();
+  }
+}
+
+} // namespace test
+} // namespace nlsr
diff --git a/tests/clock-fixture.hpp b/tests/clock-fixture.hpp
new file mode 100644
index 0000000..401f6b4
--- /dev/null
+++ b/tests/clock-fixture.hpp
@@ -0,0 +1,91 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2022,  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_CLOCK_FIXTURE_HPP
+#define NLSR_TESTS_CLOCK_FIXTURE_HPP
+
+#include <ndn-cxx/util/time-unit-test-clock.hpp>
+
+namespace nlsr {
+namespace test {
+
+namespace time = ndn::time;
+
+/** \brief A test fixture that overrides steady clock and system clock.
+ */
+class ClockFixture
+{
+public:
+  virtual
+  ~ClockFixture();
+
+  /** \brief Advance steady and system clocks.
+   *
+   *  Clocks are advanced in increments of \p tick for \p nTicks ticks.
+   *  afterTick() is called after each tick.
+   *
+   *  Exceptions thrown during I/O events are propagated to the caller.
+   *  Clock advancement will stop in the event of an exception.
+   */
+  void
+  advanceClocks(time::nanoseconds tick, size_t nTicks = 1)
+  {
+    advanceClocks(tick, tick * nTicks);
+  }
+
+  /** \brief Advance steady and system clocks.
+   *
+   *  Clocks are advanced in increments of \p tick for \p total time.
+   *  The last increment might be shorter than \p tick.
+   *  afterTick() is called after each tick.
+   *
+   *  Exceptions thrown during I/O events are propagated to the caller.
+   *  Clock advancement will stop in the event of an exception.
+   */
+  void
+  advanceClocks(time::nanoseconds tick, time::nanoseconds total);
+
+protected:
+  ClockFixture();
+
+private:
+  /** \brief Called by advanceClocks() after each clock advancement (tick).
+   *
+   *  The base class implementation is a no-op.
+   */
+  virtual void
+  afterTick()
+  {
+  }
+
+protected:
+  std::shared_ptr<time::UnitTestSteadyClock> m_steadyClock;
+  std::shared_ptr<time::UnitTestSystemClock> m_systemClock;
+};
+
+} // namespace test
+} // namespace nlsr
+
+#endif // NLSR_TESTS_CLOCK_FIXTURE_HPP
diff --git a/tests/communication/test-sync-logic-handler.cpp b/tests/communication/test-sync-logic-handler.cpp
index 3c71f74..b493290 100644
--- a/tests/communication/test-sync-logic-handler.cpp
+++ b/tests/communication/test-sync-logic-handler.cpp
@@ -20,11 +20,11 @@
  */
 
 #include "communication/sync-logic-handler.hpp"
-#include "tests/test-common.hpp"
-#include "common.hpp"
 #include "nlsr.hpp"
 
-#include <ndn-cxx/util/dummy-client-face.hpp>
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
+
 #include <boost/lexical_cast.hpp>
 
 namespace nlsr {
@@ -32,7 +32,7 @@
 
 using std::shared_ptr;
 
-class SyncLogicFixture : public UnitTestTimeFixture
+class SyncLogicFixture : public IoKeyChainFixture
 {
 public:
   SyncLogicFixture()
@@ -42,7 +42,7 @@
                        this->conf.getSiteName().toUri() +
                        "/%C1.Router/other-router/")
   {
-    addIdentity(conf.getRouterPrefix());
+    m_keyChain.createIdentity(conf.getRouterPrefix());
   }
 
   void
@@ -59,16 +59,16 @@
   }
 
 public:
-  ndn::util::DummyClientFace face{m_ioService, m_keyChain};
+  ndn::util::DummyClientFace face{m_io, m_keyChain};
   ConfParameter conf{face, m_keyChain};
   DummyConfFileProcessor confProcessor{conf, SYNC_PROTOCOL_PSYNC};
   SyncLogicHandler::IsLsaNew testIsLsaNew;
   SyncLogicHandler sync;
 
   const std::string updateNamePrefix;
-  const std::vector<Lsa::Type> lsaTypes = {Lsa::Type::NAME,
-                                           Lsa::Type::ADJACENCY,
-                                           Lsa::Type::COORDINATE};
+  const std::vector<Lsa::Type> lsaTypes{Lsa::Type::NAME,
+                                        Lsa::Type::ADJACENCY,
+                                        Lsa::Type::COORDINATE};
 };
 
 BOOST_FIXTURE_TEST_SUITE(TestSyncLogicHandler, SyncLogicFixture)
diff --git a/tests/communication/test-sync-protocol-adapter.cpp b/tests/communication/test-sync-protocol-adapter.cpp
index 0266981..74d9e23 100644
--- a/tests/communication/test-sync-protocol-adapter.cpp
+++ b/tests/communication/test-sync-protocol-adapter.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  The University of Memphis,
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -20,24 +20,24 @@
  */
 
 #include "communication/sync-protocol-adapter.hpp"
-#include "tests/test-common.hpp"
+
+#include "tests/boost-test.hpp"
+#include "tests/io-key-chain-fixture.hpp"
 
 #include <ndn-cxx/util/dummy-client-face.hpp>
 
-#include <boost/lexical_cast.hpp>
-
 namespace nlsr {
 namespace test {
 
 using namespace ndn;
 
-class SyncProtocolAdapterFixture : public UnitTestTimeFixture
+class SyncProtocolAdapterFixture : public IoKeyChainFixture
 {
 public:
   SyncProtocolAdapterFixture()
-   : syncPrefix("/localhop/ndn/nlsr/sync/")
-   , nameLsaUserPrefix("/localhop/ndn/nlsr/LSA/NAME")
-   , syncInterestLifetime(time::seconds(60))
+    : syncPrefix("/localhop/ndn/nlsr/sync")
+    , nameLsaUserPrefix("/localhop/ndn/nlsr/LSA/NAME")
+    , syncInterestLifetime(time::seconds(60))
   {
     syncPrefix.appendVersion(4);
   }
@@ -46,14 +46,14 @@
   addNodes()
   {
     for (int i = 0; i < 2; i++) {
-      faces[i] = std::make_shared<ndn::util::DummyClientFace>(m_ioService,
-                                                              util::DummyClientFace::Options{true, true});
+      faces[i] = std::make_shared<util::DummyClientFace>(m_io,
+                                                         util::DummyClientFace::Options{true, true});
       userPrefixes[i] = Name(nameLsaUserPrefix).appendNumber(i);
       nodes[i] = std::make_shared<SyncProtocolAdapter>(*faces[i], SYNC_PROTOCOL_PSYNC, syncPrefix,
                                                        userPrefixes[i],
                                                        syncInterestLifetime,
                                                        [i, this] (const ndn::Name& updateName,
-                                                                   uint64_t highSeq) {
+                                                                  uint64_t highSeq) {
                                                          prefixToSeq[i].emplace(updateName, highSeq);
                                                        });
     }
diff --git a/tests/control-commands.hpp b/tests/control-commands.hpp
deleted file mode 100644
index 4215c89..0000000
--- a/tests/control-commands.hpp
+++ /dev/null
@@ -1,62 +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_TEST_CONTROL_COMMANDS_HPP
-#define NLSR_TEST_CONTROL_COMMANDS_HPP
-
-#include <ndn-cxx/interest.hpp>
-#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
-
-namespace nlsr {
-namespace test {
-
-inline void
-extractParameters(const ndn::Interest& interest,
-                  ndn::Name::Component& verb,
-                  ndn::nfd::ControlParameters& extractedParameters,
-                  const ndn::Name& commandPrefix)
-{
-  const ndn::Name& name = interest.getName();
-  verb = name[commandPrefix.size()];
-  const ndn::Name::Component& parameterComponent = name[commandPrefix.size() + 1];
-
-  ndn::Block rawParameters = parameterComponent.blockFromValue();
-  extractedParameters.wireDecode(rawParameters);
-}
-
-inline void
-extractRibCommandParameters(const ndn::Interest& interest, ndn::Name::Component& verb,
-                            ndn::nfd::ControlParameters& extractedParameters)
-{
-  extractParameters(interest, verb, extractedParameters, ndn::Name("/localhost/nfd/rib"));
-}
-
-inline void
-extractFaceCommandParameters(const ndn::Interest& interest, ndn::Name::Component& verb,
-                             ndn::nfd::ControlParameters& extractedParameters)
-{
-  extractParameters(interest, verb, extractedParameters, ndn::Name("/localhost/nfd/faces"));
-}
-
-} // namespace test
-} // namespace nlsr
-
-#endif // NLSR_TEST_CONTROL_COMMANDS_HPP
diff --git a/tests/identity-management-fixture.cpp b/tests/identity-management-fixture.cpp
deleted file mode 100644
index b13c44a..0000000
--- a/tests/identity-management-fixture.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2022,  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/additional-description.hpp>
-
-#include <boost/filesystem.hpp>
-
-namespace nlsr {
-namespace tests {
-
-namespace v2 = ndn::security;
-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.addCustomTlv(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());
-
-  // 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
deleted file mode 100644
index 447a320..0000000
--- a/tests/identity-management-fixture.hpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2020,  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/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::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/io-fixture.hpp b/tests/io-fixture.hpp
new file mode 100644
index 0000000..b30663a
--- /dev/null
+++ b/tests/io-fixture.hpp
@@ -0,0 +1,59 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2022,  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_IO_FIXTURE_HPP
+#define NLSR_TESTS_IO_FIXTURE_HPP
+
+#include "tests/clock-fixture.hpp"
+
+#include <boost/asio/io_service.hpp>
+
+namespace nlsr {
+namespace test {
+
+class IoFixture : public ClockFixture
+{
+private:
+  void
+  afterTick() final
+  {
+    if (m_io.stopped()) {
+#if BOOST_VERSION >= 106600
+      m_io.restart();
+#else
+      m_io.reset();
+#endif
+    }
+    m_io.poll();
+  }
+
+protected:
+  boost::asio::io_service m_io;
+};
+
+} // namespace test
+} // namespace nlsr
+
+#endif // NLSR_TESTS_IO_FIXTURE_HPP
diff --git a/tests/io-key-chain-fixture.hpp b/tests/io-key-chain-fixture.hpp
new file mode 100644
index 0000000..199bd28
--- /dev/null
+++ b/tests/io-key-chain-fixture.hpp
@@ -0,0 +1,38 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2022,  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_TESTS_IO_KEY_CHAIN_FIXTURE_HPP
+#define NLSR_TESTS_IO_KEY_CHAIN_FIXTURE_HPP
+
+#include "tests/key-chain-fixture.hpp"
+#include "tests/io-fixture.hpp"
+
+namespace nlsr {
+namespace test {
+
+class IoKeyChainFixture : public IoFixture, public KeyChainFixture
+{
+};
+
+} // namespace test
+} // namespace nlsr
+
+#endif // NLSR_TESTS_IO_KEY_CHAIN_FIXTURE_HPP
diff --git a/tests/key-chain-fixture.cpp b/tests/key-chain-fixture.cpp
new file mode 100644
index 0000000..e65ff42
--- /dev/null
+++ b/tests/key-chain-fixture.cpp
@@ -0,0 +1,116 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2022,  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 "tests/key-chain-fixture.hpp"
+
+#include <ndn-cxx/util/io.hpp>
+
+#include <boost/filesystem/operations.hpp>
+
+namespace nlsr {
+namespace test {
+
+using namespace ndn::security;
+
+KeyChainFixture::KeyChainFixture()
+  : m_keyChain("pib-memory:", "tpm-memory:")
+{
+}
+
+KeyChainFixture::~KeyChainFixture()
+{
+  boost::system::error_code ec;
+  for (const auto& certFile : m_certFiles) {
+    boost::filesystem::remove(certFile, ec); // ignore error
+  }
+}
+
+bool
+KeyChainFixture::saveCert(const ndn::Data& cert, const std::string& filename)
+{
+  m_certFiles.push_back(filename);
+  try {
+    ndn::io::save(cert, filename);
+    return true;
+  }
+  catch (const ndn::io::Error&) {
+    return false;
+  }
+}
+
+bool
+KeyChainFixture::saveIdentityCert(const Identity& identity, const std::string& filename)
+{
+  Certificate cert;
+  try {
+    cert = identity.getDefaultKey().getDefaultCertificate();
+  }
+  catch (const Pib::Error&) {
+    return false;
+  }
+
+  return saveCert(cert, filename);
+}
+
+bool
+KeyChainFixture::saveIdentityCert(const ndn::Name& identityName, const std::string& filename,
+                                  bool allowCreate)
+{
+  Identity id;
+  try {
+    id = m_keyChain.getPib().getIdentity(identityName);
+  }
+  catch (const Pib::Error&) {
+    if (allowCreate) {
+      id = m_keyChain.createIdentity(identityName);
+    }
+  }
+
+  if (!id) {
+    return false;
+  }
+
+  return saveIdentityCert(id, filename);
+}
+
+Identity
+KeyChainFixture::addSubCertificate(const ndn::Name& subIdentityName,
+                                   const Identity& issuer,
+                                   const ndn::KeyParams& params)
+{
+  auto subIdentity = m_keyChain.createIdentity(subIdentityName, params);
+
+  auto request = subIdentity.getDefaultKey().getDefaultCertificate();
+  ndn::security::MakeCertificateOptions opts;
+  opts.issuerId = ndn::name::Component::fromEscapedString("parent");
+  m_keyChain.makeCertificate(request, ndn::signingByIdentity(issuer), opts);
+
+  m_keyChain.setDefaultCertificate(subIdentity.getDefaultKey(), request);
+
+  return subIdentity;
+}
+
+} // namespace test
+} // namespace nlsr
diff --git a/tests/key-chain-fixture.hpp b/tests/key-chain-fixture.hpp
new file mode 100644
index 0000000..3684cad
--- /dev/null
+++ b/tests/key-chain-fixture.hpp
@@ -0,0 +1,102 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014-2022,  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_KEY_CHAIN_FIXTURE_HPP
+#define NLSR_TESTS_KEY_CHAIN_FIXTURE_HPP
+
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/security/signing-helpers.hpp>
+
+namespace nlsr {
+namespace test {
+
+/**
+ * @brief A fixture providing an in-memory KeyChain.
+ *
+ * Test cases can use this fixture to create identities. Identities, certificates, and
+ * saved certificates are automatically removed during test teardown.
+ */
+class KeyChainFixture
+{
+protected:
+  using Certificate = ndn::security::Certificate;
+  using Identity    = ndn::security::Identity;
+  using Key         = ndn::security::Key;
+
+public:
+  /**
+   * @brief Saves an NDN certificate to a file
+   * @return true if successful, false otherwise
+   */
+  bool
+  saveCert(const ndn::Data& cert, const std::string& filename);
+
+  /**
+   * @brief Saves the default certificate of @p identity to a file
+   * @return true if successful, false otherwise
+   */
+  bool
+  saveIdentityCert(const Identity& identity, const std::string& filename);
+
+  /**
+   * @brief Saves the default certificate of the identity named @p identityName to a file
+   * @param identityName Name of the identity
+   * @param filename File name, must be writable
+   * @param allowCreate If true, create the identity if it does not exist
+   * @return true if successful, false otherwise
+   */
+  bool
+  saveIdentityCert(const ndn::Name& identityName, const std::string& filename,
+                   bool allowCreate = false);
+
+  /**
+   * @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
+   */
+  Identity
+  addSubCertificate(const ndn::Name& identityName, const Identity& issuer,
+                    const ndn::KeyParams& params = ndn::KeyChain::getDefaultKeyParams());
+
+protected:
+  KeyChainFixture();
+
+  ~KeyChainFixture();
+
+protected:
+  ndn::KeyChain m_keyChain;
+
+private:
+  std::vector<std::string> m_certFiles;
+};
+
+} // namespace test
+} // namespace nlsr
+
+#endif // NLSR_TESTS_KEY_CHAIN_FIXTURE_HPP
diff --git a/tests/main.cpp b/tests/main.cpp
index 011014d..912f0c3 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,4 +24,4 @@
  */
 
 #define BOOST_TEST_MODULE NLSR
-#include "boost-test.hpp"
+#include "tests/boost-test.hpp"
diff --git a/tests/publisher/publisher-fixture.hpp b/tests/publisher/publisher-fixture.hpp
index 3dcf103..ffc7016 100644
--- a/tests/publisher/publisher-fixture.hpp
+++ b/tests/publisher/publisher-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  The University of Memphis,
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -19,40 +19,31 @@
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NLSR_PUBLISHER_FIXTURE_HPP
-#define NLSR_PUBLISHER_FIXTURE_HPP
+#ifndef NLSR_TESTS_PUBLISHER_FIXTURE_HPP
+#define NLSR_TESTS_PUBLISHER_FIXTURE_HPP
 
 #include "publisher/dataset-interest-handler.hpp"
 #include "nlsr.hpp"
 
+#include "tests/io-key-chain-fixture.hpp"
 #include "tests/test-common.hpp"
 
-#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>
-
-using namespace ndn;
-
 namespace nlsr {
 namespace test {
 
-class PublisherFixture : public BaseFixture
+class PublisherFixture : public IoKeyChainFixture
 {
 public:
   PublisherFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , conf(face, m_keyChain)
     , confProcessor(conf)
     , nlsr(face, m_keyChain, conf)
     , lsdb(nlsr.m_lsdb)
     , rt1(nlsr.m_routingTable)
   {
-    routerId = addIdentity(conf.getRouterPrefix());
-    face.processEvents(ndn::time::milliseconds(100));
+    routerId = m_keyChain.createIdentity(conf.getRouterPrefix());
+    advanceClocks(100_ms);
   }
 
   void
@@ -65,16 +56,28 @@
   NextHop
   createNextHop(const std::string& faceUri, double cost)
   {
-    NextHop nexthop(faceUri, cost);
-    return nexthop;
+    return {faceUri, cost};
   }
 
   CoordinateLsa
   createCoordinateLsa(const std::string& origin, double radius, std::vector<double> angle)
   {
-    CoordinateLsa lsa(origin, 1, ndn::time::system_clock::now(),
-                      radius, angle);
-    return lsa;
+    return {origin, 1, ndn::time::system_clock::now(), radius, angle};
+  }
+
+  void
+  processDatasetInterest(std::function<bool(const ndn::Block&)> isSameType)
+  {
+    advanceClocks(30_ms);
+
+    BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
+    ndn::Block parser(face.sentData[0].getContent());
+    parser.parse();
+    face.sentData.clear();
+
+    auto it = parser.elements_begin();
+    BOOST_CHECK(isSameType(*it++));
+    BOOST_CHECK(it == parser.elements_end());
   }
 
 public:
@@ -91,4 +94,4 @@
 } // namespace test
 } // namespace nlsr
 
-#endif // NLSR_PUBLISHER_FIXTURE_HPP
+#endif // NLSR_TESTS_PUBLISHER_FIXTURE_HPP
diff --git a/tests/publisher/test-dataset-interest-handler.cpp b/tests/publisher/test-dataset-interest-handler.cpp
index b8a44d3..2e71585 100644
--- a/tests/publisher/test-dataset-interest-handler.cpp
+++ b/tests/publisher/test-dataset-interest-handler.cpp
@@ -22,30 +22,11 @@
 #include "publisher/dataset-interest-handler.hpp"
 #include "tlv-nlsr.hpp"
 
-#include "tests/test-common.hpp"
-#include "publisher-fixture.hpp"
+#include "tests/publisher/publisher-fixture.hpp"
 
 namespace nlsr {
 namespace test {
 
-static void
-processDatasetInterest(ndn::util::DummyClientFace& face,
-                       std::function<bool(const ndn::Block&)> isSameType)
-{
-  face.processEvents(30_ms);
-
-  BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
-
-  ndn::Block parser(face.sentData[0].getContent());
-  parser.parse();
-
-  auto it = parser.elements_begin();
-  BOOST_CHECK_EQUAL(isSameType(*it++), true);
-  BOOST_CHECK(it == parser.elements_end());
-
-  face.sentData.clear();
-}
-
 BOOST_FIXTURE_TEST_SUITE(TestDatasetInterestHandler, PublisherFixture)
 
 BOOST_AUTO_TEST_CASE(Localhost)
@@ -70,29 +51,23 @@
   const ndn::Name& DEST_ROUTER = rte1.getDestination();
 
   NextHop nh = createNextHop("udp://face-test1", 10);
-
   rt1.addNextHop(DEST_ROUTER, nh);
 
   // Request adjacency LSAs
   face.receive(ndn::Interest("/localhost/nlsr/lsdb/adjacencies").setCanBePrefix(true));
-  processDatasetInterest(face,
-    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::AdjacencyLsa; });
+  processDatasetInterest([] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::AdjacencyLsa; });
 
   // Request coordinate LSAs
   face.receive(ndn::Interest("/localhost/nlsr/lsdb/coordinates").setCanBePrefix(true));
-  processDatasetInterest(face,
-    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::CoordinateLsa; });
+  processDatasetInterest([] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::CoordinateLsa; });
 
   // Request Name LSAs
   face.receive(ndn::Interest("/localhost/nlsr/lsdb/names").setCanBePrefix(true));
-  processDatasetInterest(face,
-    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });
+  processDatasetInterest([] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });
 
   // Request Routing Table
   face.receive(ndn::Interest("/localhost/nlsr/routing-table").setCanBePrefix(true));
-  processDatasetInterest(face,
-    [] (const ndn::Block& block) {
-      return block.type() == ndn::tlv::nlsr::RoutingTable; });
+  processDatasetInterest([] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::RoutingTable; });
 }
 
 BOOST_AUTO_TEST_CASE(RouterName)
@@ -126,23 +101,19 @@
 
   // Request adjacency LSAs
   face.receive(ndn::Interest(ndn::Name(routerName).append("lsdb").append("adjacencies")).setCanBePrefix(true));
-  processDatasetInterest(face,
-    [] (const auto& block) { return block.type() == ndn::tlv::nlsr::AdjacencyLsa; });
+  processDatasetInterest([] (const auto& block) { return block.type() == ndn::tlv::nlsr::AdjacencyLsa; });
 
   // Request coordinate LSAs
   face.receive(ndn::Interest(ndn::Name(routerName).append("lsdb").append("coordinates")).setCanBePrefix(true));
-  processDatasetInterest(face,
-    [] (const auto& block) { return block.type() == ndn::tlv::nlsr::CoordinateLsa; });
+  processDatasetInterest([] (const auto& block) { return block.type() == ndn::tlv::nlsr::CoordinateLsa; });
 
   // Request Name LSAs
   face.receive(ndn::Interest(ndn::Name(routerName).append("lsdb").append("names")).setCanBePrefix(true));
-  processDatasetInterest(face,
-    [] (const auto& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });
+  processDatasetInterest([] (const auto& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });
 
   // Request Routing Table
   face.receive(ndn::Interest(ndn::Name(routerName).append("routing-table")).setCanBePrefix(true));
-  processDatasetInterest(face,
-    [] (const auto& block) { return block.type() == ndn::tlv::nlsr::RoutingTable; });
+  processDatasetInterest([] (const auto& block) { return block.type() == ndn::tlv::nlsr::RoutingTable; });
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/route/test-fib.cpp b/tests/route/test-fib.cpp
index 5c75314..9da37de 100644
--- a/tests/route/test-fib.cpp
+++ b/tests/route/test-fib.cpp
@@ -22,21 +22,20 @@
 #include "adjacency-list.hpp"
 #include "conf-parameter.hpp"
 
-#include "../test-common.hpp"
-#include "../control-commands.hpp"
+#include "tests/boost-test.hpp"
+#include "tests/io-key-chain-fixture.hpp"
 
+#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
 #include <ndn-cxx/util/dummy-client-face.hpp>
 
 namespace nlsr {
 namespace test {
 
-class FibFixture : public UnitTestTimeFixture
+class FibFixture : public IoKeyChainFixture
 {
 public:
   FibFixture()
-    : face(m_ioService, m_keyChain)
-    , conf(face, m_keyChain)
-    , adjacencies(conf.getAdjacencyList())
+    : adjacencies(conf.getAdjacencyList())
     , fib(face, m_scheduler, adjacencies, conf, m_keyChain)
     , interests(face.sentInterests)
   {
@@ -58,7 +57,8 @@
   }
 
   void
-  enableRegistrationReplyWithFaceId() {
+  enableRegistrationReplyWithFaceId()
+  {
     face.onSendInterest.connect([this] (const ndn::Interest& interest) {
       static const ndn::Name localhostRegistration("/localhost/nfd/rib");
       if (!localhostRegistration.isPrefixOf(interest.getName()))
@@ -86,10 +86,25 @@
     });
   }
 
-public:
-  ndn::util::DummyClientFace face;
+  static void
+  extractRibCommandParameters(const ndn::Interest& interest, ndn::Name::Component& verb,
+                              ndn::nfd::ControlParameters& extractedParameters)
+  {
+    static const ndn::Name commandPrefix("/localhost/nfd/rib");
 
-  ConfParameter conf;
+    const auto& name = interest.getName();
+    verb = name.at(commandPrefix.size());
+    const auto& paramComponent = name.at(commandPrefix.size() + 1);
+    extractedParameters.wireDecode(paramComponent.blockFromValue());
+  }
+
+private:
+  ndn::Scheduler m_scheduler{m_io};
+
+public:
+  ndn::util::DummyClientFace face{m_io, m_keyChain};
+
+  ConfParameter conf{face, m_keyChain};
   AdjacencyList& adjacencies;
   Fib fib;
   std::vector<ndn::Interest>& interests;
@@ -402,7 +417,7 @@
   int numRegister = 0;
   // Do not expect any unregisters, just registers which will update the cost in NFD
   for (const auto& i : face.sentInterests) {
-    if (i.getName().getPrefix(4) == "/localhost/nfd/rib/unregister/") {
+    if (i.getName().getPrefix(4) == "/localhost/nfd/rib/unregister") {
       BOOST_CHECK(false);
     }
     else {
diff --git a/tests/route/test-hyperbolic-calculator.cpp b/tests/route/test-hyperbolic-calculator.cpp
index 30f8ced..f830c94 100644
--- a/tests/route/test-hyperbolic-calculator.cpp
+++ b/tests/route/test-hyperbolic-calculator.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2020,  The University of Memphis,
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -19,8 +19,6 @@
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "../test-common.hpp"
-
 #include "route/routing-table-calculator.hpp"
 
 #include "adjacency-list.hpp"
@@ -29,7 +27,8 @@
 #include "route/map.hpp"
 #include "route/routing-table.hpp"
 
-#include <ndn-cxx/util/dummy-client-face.hpp>
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 namespace nlsr {
 namespace test {
@@ -38,11 +37,11 @@
 using ndn::time::system_clock;
 static const system_clock::TimePoint MAX_TIME = system_clock::TimePoint::max();
 
-class HyperbolicCalculatorFixture : public BaseFixture
+class HyperbolicCalculatorFixture : public IoKeyChainFixture
 {
 public:
   HyperbolicCalculatorFixture()
-    : face(m_ioService, m_keyChain)
+    : face(m_io, m_keyChain)
     , conf(face, m_keyChain)
     , nlsr(face, m_keyChain, conf)
     , routingTable(nlsr.m_routingTable)
diff --git a/tests/route/test-link-state-calculator.cpp b/tests/route/test-link-state-calculator.cpp
index 057b1c8..46c27fe 100644
--- a/tests/route/test-link-state-calculator.cpp
+++ b/tests/route/test-link-state-calculator.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2020,  The University of Memphis,
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -22,14 +22,14 @@
 #include "route/routing-table-calculator.hpp"
 
 #include "adjacency-list.hpp"
+#include "adjacent.hpp"
 #include "lsdb.hpp"
 #include "nlsr.hpp"
-#include "../test-common.hpp"
 #include "route/map.hpp"
 #include "route/routing-table.hpp"
-#include "adjacent.hpp"
 
-#include <ndn-cxx/util/dummy-client-face.hpp>
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 namespace nlsr {
 namespace test {
@@ -37,11 +37,11 @@
 static const ndn::time::system_clock::TimePoint MAX_TIME =
   ndn::time::system_clock::TimePoint::max();
 
-class LinkStateCalculatorFixture : public BaseFixture
+class LinkStateCalculatorFixture : public IoKeyChainFixture
 {
 public:
   LinkStateCalculatorFixture()
-    : face(m_ioService, m_keyChain)
+    : face(m_io, m_keyChain)
     , conf(face, m_keyChain)
     , confProcessor(conf)
     , nlsr(face, m_keyChain, conf)
diff --git a/tests/route/test-name-prefix-table.cpp b/tests/route/test-name-prefix-table.cpp
index fbe6c5a..9c9833f 100644
--- a/tests/route/test-name-prefix-table.cpp
+++ b/tests/route/test-name-prefix-table.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  The University of Memphis,
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -23,21 +23,18 @@
 #include "route/fib.hpp"
 #include "route/routing-table.hpp"
 #include "lsdb.hpp"
-#include "../test-common.hpp"
 
-#include <ndn-cxx/util/dummy-client-face.hpp>
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 namespace nlsr {
 namespace test {
 
-class NamePrefixTableFixture : public UnitTestTimeFixture
+class NamePrefixTableFixture : public IoKeyChainFixture
 {
 public:
   NamePrefixTableFixture()
-    : face(m_ioService, m_keyChain)
-    , conf(face, m_keyChain)
-    , confProcessor(conf)
-    , lsdb(face, m_keyChain, conf)
+    : lsdb(face, m_keyChain, conf)
     , fib(face, m_scheduler, conf.getAdjacencyList(), conf, m_keyChain)
     , rt(m_scheduler, lsdb, conf)
     , npt(conf.getRouterPrefix(), fib, rt, rt.afterRoutingChange, lsdb.onLsdbModified)
@@ -52,10 +49,13 @@
     return it != npt.end();
   }
 
+private:
+  ndn::Scheduler m_scheduler{m_io};
+
 public:
-  ndn::util::DummyClientFace face;
-  ConfParameter conf;
-  DummyConfFileProcessor confProcessor;
+  ndn::util::DummyClientFace face{m_io, m_keyChain};
+  ConfParameter conf{face, m_keyChain};
+  DummyConfFileProcessor confProcessor{conf};
 
   Lsdb lsdb;
   Fib fib;
diff --git a/tests/route/test-routing-table.cpp b/tests/route/test-routing-table.cpp
index 5624ad8..15ad958 100644
--- a/tests/route/test-routing-table.cpp
+++ b/tests/route/test-routing-table.cpp
@@ -23,30 +23,24 @@
 #include "route/routing-table-entry.hpp"
 #include "route/nexthop.hpp"
 
+#include "tests/io-key-chain-fixture.hpp"
 #include "tests/test-common.hpp"
 
 namespace nlsr {
 namespace test {
 
-class RoutingTableFixture : public UnitTestTimeFixture
+class RoutingTableFixture : public IoKeyChainFixture
 {
-public:
-  RoutingTableFixture()
-    : face(m_ioService, m_keyChain, {true, true})
-    , conf(face, m_keyChain)
-    , confProcessor(conf)
-    , lsdb(face, m_keyChain, conf)
-    , rt(m_scheduler, lsdb, conf)
-  {
-  }
+private:
+  ndn::Scheduler m_scheduler{m_io};
 
 public:
-  ndn::util::DummyClientFace face;
-  ConfParameter conf;
-  DummyConfFileProcessor confProcessor;
+  ndn::util::DummyClientFace face{m_io, m_keyChain, {true, true}};
+  ConfParameter conf{face, m_keyChain};
+  DummyConfFileProcessor confProcessor{conf};
 
-  Lsdb lsdb;
-  RoutingTable rt;
+  Lsdb lsdb{face, m_keyChain, conf};
+  RoutingTable rt{m_scheduler, lsdb, conf};
 };
 
 BOOST_AUTO_TEST_SUITE(TestRoutingTable)
diff --git a/tests/security/test-certificate-store.cpp b/tests/security/test-certificate-store.cpp
index 216aba5..46c9524 100644
--- a/tests/security/test-certificate-store.cpp
+++ b/tests/security/test-certificate-store.cpp
@@ -20,12 +20,14 @@
  */
 
 #include "security/certificate-store.hpp"
-
-#include "tests/test-common.hpp"
 #include "nlsr.hpp"
 #include "lsdb.hpp"
 
-#include <ndn-cxx/security/key-chain.hpp>
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
+
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/property_tree/info_parser.hpp>
 
@@ -34,11 +36,11 @@
 
 using std::shared_ptr;
 
-class CertificateStoreFixture : public UnitTestTimeFixture
+class CertificateStoreFixture : public IoKeyChainFixture
 {
 public:
   CertificateStoreFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , conf(face, m_keyChain, "unit-test-nlsr.conf")
     , confProcessor(conf, SYNC_PROTOCOL_PSYNC, HYPERBOLIC_STATE_OFF,
                     "/ndn/", "/site", "/%C1.Router/router1")
@@ -51,10 +53,9 @@
     , nlsr(face, m_keyChain, conf)
     , lsdb(nlsr.getLsdb())
     , certStore(face, conf, lsdb)
-    , ROOT_CERT_PATH(boost::filesystem::current_path() / std::string("root.cert"))
-
+    , ROOT_CERT_PATH(boost::filesystem::current_path() / "root.cert")
   {
-    rootId = addIdentity(rootIdName);
+    rootId = m_keyChain.createIdentity(rootIdName);
     siteIdentity = addSubCertificate(siteIdentityName, rootId);
     opIdentity = addSubCertificate(opIdentityName, siteIdentity);
     routerId = addSubCertificate(routerIdName, opIdentity);
@@ -148,7 +149,7 @@
 
 BOOST_AUTO_TEST_CASE(RetrieveCert)
 {
-  ndn::util::DummyClientFace consumer(m_ioService);
+  ndn::util::DummyClientFace consumer(m_io);
   consumer.linkTo(face);
 
   auto checkRetrieve = [&] (const ndn::Name& interestName, bool canBePrefix, const ndn::Name& dataName) {
diff --git a/tests/test-common.cpp b/tests/test-common.cpp
index b2db763..3a1ffeb 100644
--- a/tests/test-common.cpp
+++ b/tests/test-common.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2020,  The University of Memphis,
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -18,18 +18,26 @@
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "test-common.hpp"
+#include "tests/test-common.hpp"
+
+#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
 
 namespace nlsr {
 namespace test {
 
+std::shared_ptr<ndn::Data>
+makeData(const ndn::Name& name)
+{
+  auto data = std::make_shared<ndn::Data>(name);
+  return signData(data);
+}
+
 ndn::Data&
 signData(ndn::Data& data)
 {
-  data.setSignatureInfo(ndn::SignatureInfo(ndn::tlv::SignatureTypeValue::SignatureSha256WithRsa));
-  data.setSignatureValue(ndn::encoding::makeEmptyBlock(ndn::tlv::SignatureValue).getBuffer());
+  data.setSignatureInfo(ndn::SignatureInfo(ndn::tlv::NullSignature));
+  data.setSignatureValue(std::make_shared<ndn::Buffer>());
   data.wireEncode();
-
   return data;
 }
 
@@ -40,7 +48,7 @@
   for (const auto& interest : face.sentInterests) {
     if (interest.getName().size() > 4 &&
         interest.getName().get(3) == ndn::name::Component("register")) {
-      ndn::name::Component test = interest.getName().get(4);
+      auto test = interest.getName().get(4);
       ndn::nfd::ControlParameters params(test.blockFromValue());
       if (params.getName() == prefix) {
         registerCommandEmitted = true;
@@ -51,31 +59,5 @@
   BOOST_CHECK(registerCommandEmitted);
 }
 
-MockNfdMgmtFixture::MockNfdMgmtFixture()
-  : m_face(m_ioService, m_keyChain, {true, true})
-{
-}
-
-void
-MockNfdMgmtFixture::signDatasetReply(ndn::Data& data)
-{
-  signData(data);
-}
-
-void
-UnitTestTimeFixture::advanceClocks(const ndn::time::nanoseconds& tick, size_t nTicks)
-{
-  for (size_t i = 0; i < nTicks; ++i) {
-    steadyClock->advance(tick);
-    systemClock->advance(tick);
-
-    if (m_ioService.stopped()) {
-      m_ioService.reset();
-    }
-
-    m_ioService.poll();
-  }
-}
-
 } // namespace test
 } // namespace nlsr
diff --git a/tests/test-common.hpp b/tests/test-common.hpp
index 2a1e607..5c95a0c 100644
--- a/tests/test-common.hpp
+++ b/tests/test-common.hpp
@@ -19,34 +19,35 @@
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NLSR_TEST_COMMON_HPP
-#define NLSR_TEST_COMMON_HPP
+#ifndef NLSR_TESTS_TEST_COMMON_HPP
+#define NLSR_TESTS_TEST_COMMON_HPP
 
-#include "common.hpp"
 #include "conf-parameter.hpp"
-#include "route/fib.hpp"
 
-#include "boost-test.hpp"
-#include "identity-management-fixture.hpp"
+#include "tests/boost-test.hpp"
 
-#include <boost/asio.hpp>
-
-#include <ndn-cxx/face.hpp>
-#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/data.hpp>
 #include <ndn-cxx/util/dummy-client-face.hpp>
-#include <ndn-cxx/util/scheduler.hpp>
-#include <ndn-cxx/util/time-unit-test-clock.hpp>
 
 namespace nlsr {
 namespace test {
 
+/**
+ * \brief Create a Data with a null (i.e., empty) signature
+ *
+ * If a "real" signature is desired, use KeyChainFixture and sign again with `m_keyChain`.
+ */
+std::shared_ptr<ndn::Data>
+makeData(const ndn::Name& name);
+
+/**
+ * \brief Add a null signature to \p data
+ */
 ndn::Data&
 signData(ndn::Data& data);
 
-void
-checkPrefixRegistered(const ndn::util::DummyClientFace& face, const ndn::Name& prefix);
-
-/** \brief add a fake signature to Data
+/**
+ * \brief Add a null signature to \p data
  */
 inline std::shared_ptr<ndn::Data>
 signData(std::shared_ptr<ndn::Data> data)
@@ -55,132 +56,18 @@
   return data;
 }
 
-class BaseFixture : public tests::IdentityManagementFixture
-{
-public:
-  BaseFixture()
-    : m_scheduler(m_ioService)
-  {
-  }
-
-protected:
-  boost::asio::io_service m_ioService;
-  ndn::Scheduler m_scheduler;
-};
-
-class UnitTestTimeFixture : public BaseFixture
-{
-protected:
-  UnitTestTimeFixture()
-    : steadyClock(std::make_shared<ndn::time::UnitTestSteadyClock>())
-    , systemClock(std::make_shared<ndn::time::UnitTestSystemClock>())
-  {
-    ndn::time::setCustomClocks(steadyClock, systemClock);
-  }
-
-  ~UnitTestTimeFixture()
-  {
-    ndn::time::setCustomClocks(nullptr, nullptr);
-  }
-
-  void
-  advanceClocks(const ndn::time::nanoseconds& tick, size_t nTicks = 1);
-
-protected:
-  std::shared_ptr<ndn::time::UnitTestSteadyClock> steadyClock;
-  std::shared_ptr<ndn::time::UnitTestSystemClock> systemClock;
-};
-
-class MockNfdMgmtFixture : public UnitTestTimeFixture
-{
-public:
-  MockNfdMgmtFixture();
-
-  virtual
-  ~MockNfdMgmtFixture() = default;
-
-  /** \brief send one WireEncodable in reply to StatusDataset request
-   *  \param prefix dataset prefix without version and segment
-   *  \param payload payload block
-   *  \note payload must fit in one Data
-   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
-   */
-  template<typename T>
-  void
-  sendDataset(const ndn::Name& prefix, const T& payload)
-  {
-    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T>));
-
-    this->sendDatasetReply(prefix, payload.wireEncode());
-  }
-
-  /** \brief send two WireEncodables in reply to StatusDataset request
-   *  \param prefix dataset prefix without version and segment
-   *  \param payload1 first vector item
-   *  \param payload2 second vector item
-   *  \note all payloads must fit in one Data
-   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
-   */
-  template<typename T1, typename T2>
-  void
-  sendDataset(const ndn::Name& prefix, const T1& payload1, const T2& payload2)
-  {
-    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T1>));
-    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T2>));
-
-    ndn::encoding::EncodingBuffer buffer;
-    payload2.wireEncode(buffer);
-    payload1.wireEncode(buffer);
-
-    this->sendDatasetReply(prefix, buffer);
-  }
-
-  /** \brief send a payload in reply to StatusDataset request
-   *  \param name dataset prefix without version and segment
-   *  \param contentArgs passed to Data::setContent
-   */
-  template<typename ...ContentArgs>
-  void
-  sendDatasetReply(ndn::Name name, ContentArgs&&... contentArgs)
-  {
-    name.appendVersion().appendSegment(0);
-
-    // 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 (m_face.sentInterests.empty()) {
-      BOOST_WARN_MESSAGE(false, "no Interest expressed");
-    }
-    else {
-      BOOST_WARN_MESSAGE(m_face.sentInterests.back().getName().isPrefixOf(name),
-                         "last Interest " << m_face.sentInterests.back().getName() <<
-                         " cannot be satisfied by this Data " << name);
-    }
-
-    auto data = std::make_shared<ndn::Data>(name);
-    data->setFreshnessPeriod(1_s);
-    data->setFinalBlock(name[-1]);
-    data->setContent(std::forward<ContentArgs>(contentArgs)...);
-    this->signDatasetReply(*data);
-    m_face.receive(*data);
-  }
-
-  virtual void
-  signDatasetReply(ndn::Data& data);
-
-public:
-  ndn::util::DummyClientFace m_face;
-};
+void
+checkPrefixRegistered(const ndn::util::DummyClientFace& face, const ndn::Name& prefix);
 
 class DummyConfFileProcessor
 {
-  typedef std::function<void(ConfParameter&)> AfterConfProcessing;
-
 public:
   DummyConfFileProcessor(ConfParameter& conf,
                          SyncProtocol protocol = SYNC_PROTOCOL_PSYNC,
-                         int32_t hyperbolicState = HYPERBOLIC_STATE_OFF,
-                         ndn::Name networkName = "/ndn", ndn::Name siteName = "/site",
-                         ndn::Name routerName = "/%C1.Router/this-router")
+                         HyperbolicState hyperbolicState = HYPERBOLIC_STATE_OFF,
+                         const ndn::Name& networkName = "/ndn",
+                         const ndn::Name& siteName = "/site",
+                         const ndn::Name& routerName = "/%C1.Router/this-router")
   {
     conf.setNetwork(networkName);
     conf.setSiteName(siteName);
@@ -194,4 +81,4 @@
 } // namespace test
 } // namespace nlsr
 
-#endif // NLSR_TEST_COMMON_HPP
+#endif // NLSR_TESTS_TEST_COMMON_HPP
diff --git a/tests/test-conf-file-processor.cpp b/tests/test-conf-file-processor.cpp
index bacae9f..05e1a94 100644
--- a/tests/test-conf-file-processor.cpp
+++ b/tests/test-conf-file-processor.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2020,  The University of Memphis,
+/*
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -20,12 +20,13 @@
  **/
 
 #include "conf-file-processor.hpp"
-#include "test-common.hpp"
+
+#include "tests/boost-test.hpp"
+#include "tests/io-key-chain-fixture.hpp"
 
 #include <fstream>
-
-#include <boost/filesystem.hpp>
 #include <boost/algorithm/string.hpp>
+
 #include <ndn-cxx/util/dummy-client-face.hpp>
 
 namespace nlsr {
@@ -118,16 +119,16 @@
                                              SECTION_HYPERBOLIC_ANGLES_ON + SECTION_FIB +
                                              SECTION_ADVERTISING;
 
-class ConfFileProcessorFixture : public BaseFixture
+class ConfFileProcessorFixture : public IoKeyChainFixture
 {
 public:
   ConfFileProcessorFixture()
-    : face(m_ioService, m_keyChain)
+    : face(m_io, m_keyChain)
     , conf(face, m_keyChain, "unit-test-nlsr.conf")
   {
   }
 
-  ~ConfFileProcessorFixture()
+  ~ConfFileProcessorFixture() override
   {
     remove("unit-test-nlsr.conf");
   }
@@ -375,8 +376,8 @@
 
 BOOST_AUTO_TEST_CASE(LoadCertToPublish)
 {
-  auto identity = addIdentity("/TestNLSR/identity");
-  saveCertificate(identity, "cert-to-publish.cert");
+  auto identity = m_keyChain.createIdentity("/TestNLSR/identity");
+  saveIdentityCert(identity, "cert-to-publish.cert");
 
   const std::string SECTION_SECURITY = R"CONF(
       security
diff --git a/tests/test-hello-protocol.cpp b/tests/test-hello-protocol.cpp
index efd8eac..6ea3449 100644
--- a/tests/test-hello-protocol.cpp
+++ b/tests/test-hello-protocol.cpp
@@ -21,16 +21,18 @@
 
 #include "hello-protocol.hpp"
 #include "nlsr.hpp"
-#include "test-common.hpp"
+
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 namespace nlsr {
 namespace test {
 
-class HelloProtocolFixture : public UnitTestTimeFixture
+class HelloProtocolFixture : public IoKeyChainFixture
 {
 public:
   HelloProtocolFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , conf(face, m_keyChain)
     , confProcessor(conf)
     , adjList(conf.getAdjacencyList())
diff --git a/tests/test-home-fixture.hpp b/tests/test-home-fixture.hpp
deleted file mode 100644
index e712f25..0000000
--- a/tests/test-home-fixture.hpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2020,  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 <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);
-  }
-
-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-lsa-rule.cpp b/tests/test-lsa-rule.cpp
index 557b540..a2d0481 100644
--- a/tests/test-lsa-rule.cpp
+++ b/tests/test-lsa-rule.cpp
@@ -19,31 +19,28 @@
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "test-common.hpp"
 #include "nlsr.hpp"
 #include "security/certificate-store.hpp"
 
-#include <ndn-cxx/interest.hpp>
-#include <ndn-cxx/security/key-chain.hpp>
-#include <ndn-cxx/security/signing-helpers.hpp>
-#include <ndn-cxx/security/signing-info.hpp>
-#include <ndn-cxx/util/dummy-client-face.hpp>
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
-#include <boost/filesystem.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/property_tree/info_parser.hpp>
 #include <boost/property_tree/ptree.hpp>
 
-using namespace ndn;
-
 namespace nlsr {
 namespace test {
 
-class LsaRuleFixture : public UnitTestTimeFixture
+using namespace ndn;
+
+class LsaRuleFixture : public IoKeyChainFixture
 {
 public:
   LsaRuleFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , rootIdName("/ndn")
     , siteIdentityName("/ndn/edu/test-site")
     , opIdentityName("/ndn/edu/test-site/%C1.Operator/op1")
@@ -54,7 +51,7 @@
     , lsdb(face, m_keyChain, confParam)
     , ROOT_CERT_PATH(boost::filesystem::current_path() / std::string("root.cert"))
   {
-    rootId = addIdentity(rootIdName);
+    rootId = m_keyChain.createIdentity(rootIdName);
     siteIdentity = addSubCertificate(siteIdentityName, rootId);
     opIdentity = addSubCertificate(opIdentityName, siteIdentity);
     routerId = addSubCertificate(routerIdName, opIdentity);
@@ -63,7 +60,7 @@
     // previously this was done by in nlsr ctor
     confParam.initializeKey();
 
-    saveCertificate(rootId, ROOT_CERT_PATH.string());
+    saveIdentityCert(rootId, ROOT_CERT_PATH.string());
 
     for (const auto& id : {rootId, siteIdentity, opIdentity, routerId}) {
       const auto& cert = id.getDefaultKey().getDefaultCertificate();
diff --git a/tests/test-lsa-segment-storage.cpp b/tests/test-lsa-segment-storage.cpp
index 3110e87..592ea90 100644
--- a/tests/test-lsa-segment-storage.cpp
+++ b/tests/test-lsa-segment-storage.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  Regents of the University of California,
+ * Copyright (c) 2014-2022,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -23,19 +23,21 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "test-common.hpp"
 #include "nlsr.hpp"
 #include "name-prefix-list.hpp"
 // #include "lsa.hpp"
 
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
+
 namespace nlsr {
 namespace test {
 
-class LsaSegmentStorageFixture : public UnitTestTimeFixture
+class LsaSegmentStorageFixture : public IoKeyChainFixture
 {
 public:
   LsaSegmentStorageFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , conf(face, m_keyChain)
     , confProcessor(conf)
     , nlsr(face, m_keyChain, conf)
diff --git a/tests/test-lsa.cpp b/tests/test-lsa.cpp
index d89fef6..9fb6863 100644
--- a/tests/test-lsa.cpp
+++ b/tests/test-lsa.cpp
@@ -22,11 +22,10 @@
 #include "lsa/name-lsa.hpp"
 #include "lsa/adj-lsa.hpp"
 #include "lsa/coordinate-lsa.hpp"
-#include "test-common.hpp"
 #include "adjacent.hpp"
 #include "name-prefix-list.hpp"
 
-#include <ndn-cxx/util/time.hpp>
+#include "tests/boost-test.hpp"
 
 namespace nlsr {
 namespace test {
diff --git a/tests/test-lsdb.cpp b/tests/test-lsdb.cpp
index db1c60b..f1b46a6 100644
--- a/tests/test-lsdb.cpp
+++ b/tests/test-lsdb.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  The University of Memphis,
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -20,12 +20,14 @@
  */
 
 #include "lsdb.hpp"
-
-#include "test-common.hpp"
 #include "lsa/lsa.hpp"
 #include "name-prefix-list.hpp"
 
-#include <ndn-cxx/util/dummy-client-face.hpp>
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
+
+#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
+#include <ndn-cxx/security/validator-null.hpp>
 #include <ndn-cxx/util/segment-fetcher.hpp>
 
 #include <unistd.h>
@@ -33,18 +35,18 @@
 namespace nlsr {
 namespace test {
 
-class LsdbFixture : public UnitTestTimeFixture
+class LsdbFixture : public IoKeyChainFixture
 {
 public:
   LsdbFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , conf(face, m_keyChain)
     , confProcessor(conf)
     , lsdb(face, m_keyChain, conf)
     , REGISTER_COMMAND_PREFIX("/localhost/nfd/rib")
     , REGISTER_VERB("register")
   {
-    addIdentity("/ndn/site/%C1.Router/this-router");
+    m_keyChain.createIdentity("/ndn/site/%C1.Router/this-router");
 
     advanceClocks(10_ms);
     face.sentInterests.clear();
@@ -57,25 +59,18 @@
     const ndn::Name& name = interest.getName();
     verb = name[REGISTER_COMMAND_PREFIX.size()];
     const ndn::Name::Component& parameterComponent = name[REGISTER_COMMAND_PREFIX.size() + 1];
-
-    ndn::Block rawParameters = parameterComponent.blockFromValue();
-    extractedParameters.wireDecode(rawParameters);
+    extractedParameters.wireDecode(parameterComponent.blockFromValue());
   }
 
   void
   areNamePrefixListsEqual(NamePrefixList& lhs, NamePrefixList& rhs)
   {
-
-    typedef std::list<ndn::Name> NameList;
-
-    NameList lhsList = lhs.getNames();
-    NameList rhsList = rhs.getNames();
-
+    auto lhsList = lhs.getNames();
+    auto rhsList = rhs.getNames();
     BOOST_REQUIRE_EQUAL(lhsList.size(), rhsList.size());
 
-    NameList::iterator i = lhsList.begin();
-    NameList::iterator j = rhsList.begin();
-
+    auto i = lhsList.begin();
+    auto j = rhsList.begin();
     for (; i != lhsList.end(); ++i, ++j) {
       BOOST_CHECK_EQUAL(*i, *j);
     }
@@ -232,7 +227,7 @@
   lsdb.installLsa(nameLsa);
 
   // Create another Lsdb and expressInterest
-  ndn::util::DummyClientFace face2(m_ioService, m_keyChain, {true, true});
+  ndn::util::DummyClientFace face2(m_io, m_keyChain, {true, true});
   face.linkTo(face2);
 
   ConfParameter conf2(face2, m_keyChain);
@@ -277,7 +272,7 @@
   ndn::Name interestName("/localhop/ndn/nlsr/LSA/site/%C1.Router/this-router/NAME/");
   interestName.appendNumber(seqNo);
 
-  ndn::util::DummyClientFace face2(m_ioService, m_keyChain, {true, true});
+  ndn::util::DummyClientFace face2(m_io, m_keyChain, {true, true});
   face.linkTo(face2);
 
   auto fetcher = ndn::util::SegmentFetcher::start(face2, ndn::Interest(interestName),
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index 43c5baf..e888acf 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -20,15 +20,88 @@
  */
 
 #include "nlsr.hpp"
-#include "test-common.hpp"
-#include "control-commands.hpp"
 #include "logger.hpp"
 
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
+
 #include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
 
 namespace nlsr {
 namespace test {
 
+class MockNfdMgmtFixture : public IoKeyChainFixture
+{
+public:
+  /** \brief send one WireEncodable in reply to StatusDataset request
+   *  \param prefix dataset prefix without version and segment
+   *  \param payload payload block
+   *  \note payload must fit in one Data
+   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
+   */
+  template<typename T>
+  void
+  sendDataset(const ndn::Name& prefix, const T& payload)
+  {
+    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T>));
+
+    this->sendDatasetReply(prefix, payload.wireEncode());
+  }
+
+  /** \brief send two WireEncodables in reply to StatusDataset request
+   *  \param prefix dataset prefix without version and segment
+   *  \param payload1 first vector item
+   *  \param payload2 second vector item
+   *  \note all payloads must fit in one Data
+   *  \pre Interest for dataset has been expressed, sendDataset has not been invoked
+   */
+  template<typename T1, typename T2>
+  void
+  sendDataset(const ndn::Name& prefix, const T1& payload1, const T2& payload2)
+  {
+    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T1>));
+    BOOST_CONCEPT_ASSERT((ndn::WireEncodable<T2>));
+
+    ndn::encoding::EncodingBuffer buffer;
+    payload2.wireEncode(buffer);
+    payload1.wireEncode(buffer);
+
+    this->sendDatasetReply(prefix, buffer);
+  }
+
+  /** \brief send a payload in reply to StatusDataset request
+   *  \param name dataset prefix without version and segment
+   *  \param contentArgs passed to Data::setContent
+   */
+  template<typename ...ContentArgs>
+  void
+  sendDatasetReply(ndn::Name name, ContentArgs&&... contentArgs)
+  {
+    name.appendVersion().appendSegment(0);
+
+    // 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 (m_face.sentInterests.empty()) {
+      BOOST_WARN_MESSAGE(false, "no Interest expressed");
+    }
+    else {
+      BOOST_WARN_MESSAGE(m_face.sentInterests.back().getName().isPrefixOf(name),
+                         "last Interest " << m_face.sentInterests.back().getName() <<
+                         " cannot be satisfied by this Data " << name);
+    }
+
+    auto data = std::make_shared<ndn::Data>(name);
+    data->setFreshnessPeriod(1_s);
+    data->setFinalBlock(name[-1]);
+    data->setContent(std::forward<ContentArgs>(contentArgs)...);
+    signData(*data);
+    m_face.receive(*data);
+  }
+
+public:
+  ndn::util::DummyClientFace m_face{m_io, m_keyChain, {true, true}};
+};
+
 class NlsrFixture : public MockNfdMgmtFixture
 {
 public:
@@ -41,7 +114,7 @@
     , nSuccessCallbacks(0)
     , nFailureCallbacks(0)
   {
-    addIdentity(conf.getRouterPrefix());
+    m_keyChain.createIdentity(conf.getRouterPrefix());
   }
 
   void
diff --git a/tests/test-sequencing-manager.cpp b/tests/test-sequencing-manager.cpp
index 218952a..57c09f5 100644
--- a/tests/test-sequencing-manager.cpp
+++ b/tests/test-sequencing-manager.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2020,  The University of Memphis,
+/*
+ * Copyright (c) 2014-2022,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -20,23 +20,22 @@
  **/
 
 #include "sequencing-manager.hpp"
-#include "test-common.hpp"
 
-#include <boost/filesystem.hpp>
-#include <string>
-#include <iostream>
+#include "tests/boost-test.hpp"
+
+#include <boost/filesystem/operations.hpp>
 #include <fstream>
 
-using namespace ndn;
-
 namespace nlsr {
 namespace test {
 
-class SequencingManagerFixture : public BaseFixture
+using namespace ndn;
+
+class SequencingManagerFixture
 {
 public:
   SequencingManagerFixture()
-  : m_seqManager("/tmp", HYPERBOLIC_STATE_OFF)
+    : m_seqManager("/tmp", HYPERBOLIC_STATE_OFF)
   {
   }
 
diff --git a/tests/test-statistics.cpp b/tests/test-statistics.cpp
index 4a5dc5b..7822b76 100644
--- a/tests/test-statistics.cpp
+++ b/tests/test-statistics.cpp
@@ -24,19 +24,19 @@
 #include "lsdb.hpp"
 #include "nlsr.hpp"
 
-#include "test-common.hpp"
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
-#include <ndn-cxx/util/dummy-client-face.hpp>
 #include <boost/lexical_cast.hpp>
 
 namespace nlsr {
 namespace test {
 
-class StatisticsFixture : public UnitTestTimeFixture
+class StatisticsFixture : public IoKeyChainFixture
 {
 public:
   StatisticsFixture()
-    : face(m_ioService, m_keyChain)
+    : face(m_io, m_keyChain)
     , conf(face, m_keyChain)
     , confProcessor(conf)
     , nlsr(face, m_keyChain, conf)
@@ -47,7 +47,7 @@
     // Otherwise code coverage node fails with default 60 seconds lifetime
     conf.setSyncInterestLifetime(1000);
 
-    addIdentity(conf.getRouterPrefix());
+    m_keyChain.createIdentity(conf.getRouterPrefix());
 
     this->advanceClocks(ndn::time::milliseconds(1), 10);
     face.sentInterests.clear();
diff --git a/tests/update/test-advertise-crash.cpp b/tests/update/test-advertise-crash.cpp
index 8925469..e2ded04 100644
--- a/tests/update/test-advertise-crash.cpp
+++ b/tests/update/test-advertise-crash.cpp
@@ -21,16 +21,17 @@
 
 #include "nlsr.hpp"
 
-#include "../test-common.hpp"
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 namespace nlsr {
 namespace test {
 
-class AdvertiseCrashFixture : public UnitTestTimeFixture
+class AdvertiseCrashFixture : public IoKeyChainFixture
 {
 public:
   AdvertiseCrashFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , conf(face, m_keyChain)
     , confProcessor(conf)
     , nlsr(face, m_keyChain, conf)
@@ -49,7 +50,7 @@
 
     std::vector<ndn::nfd::FaceStatus> faces{payload1};
 
-    addIdentity(conf.getRouterPrefix());
+    m_keyChain.createIdentity(conf.getRouterPrefix());
 
     // Simulate a callback with fake response
     // This will trigger the undefined behavior found
diff --git a/tests/update/test-nfd-rib-command-processor.cpp b/tests/update/test-nfd-rib-command-processor.cpp
index c9be622..1ea89dc 100644
--- a/tests/update/test-nfd-rib-command-processor.cpp
+++ b/tests/update/test-nfd-rib-command-processor.cpp
@@ -24,26 +24,26 @@
 #include "conf-parameter.hpp"
 #include "nlsr.hpp"
 
-#include "../test-common.hpp"
-#include "../control-commands.hpp"
+#include "tests/io-key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 #include <boost/lexical_cast.hpp>
 
 namespace nlsr {
 namespace test {
 
-class NfdRibCommandProcessorFixture : public UnitTestTimeFixture
+class NfdRibCommandProcessorFixture : public IoKeyChainFixture
 {
 public:
   NfdRibCommandProcessorFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , conf(face, m_keyChain)
     , confProcessor(conf)
     , nlsr(face, m_keyChain, conf)
     , namePrefixes(conf.getNamePrefixList())
     , processor(nlsr.m_nfdRibCommandProcessor)
   {
-    addIdentity(conf.getRouterPrefix());
+    m_keyChain.createIdentity(conf.getRouterPrefix());
 
     this->advanceClocks(ndn::time::milliseconds(10), 10);
     face.sentInterests.clear();
diff --git a/tests/update/test-prefix-update-processor.cpp b/tests/update/test-prefix-update-processor.cpp
index ac50943..52fb7b1 100644
--- a/tests/update/test-prefix-update-processor.cpp
+++ b/tests/update/test-prefix-update-processor.cpp
@@ -22,29 +22,29 @@
 #include "update/prefix-update-processor.hpp"
 #include "nlsr.hpp"
 
-#include "tests/control-commands.hpp"
+#include "tests/io-key-chain-fixture.hpp"
 #include "tests/test-common.hpp"
 
-#include <ndn-cxx/mgmt/nfd/control-response.hpp>
+#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
 #include <ndn-cxx/security/interest-signer.hpp>
-#include <ndn-cxx/security/pib/identity.hpp>
 #include <ndn-cxx/security/signing-helpers.hpp>
 
-#include <boost/filesystem.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/property_tree/info_parser.hpp>
 #include <boost/property_tree/ptree.hpp>
 
-using namespace ndn;
-
 namespace nlsr {
 namespace test {
 
-class PrefixUpdateFixture : public UnitTestTimeFixture
+using namespace ndn;
+
+class PrefixUpdateFixture : public IoKeyChainFixture
 {
 public:
   PrefixUpdateFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , siteIdentityName(ndn::Name("site"))
     , opIdentityName(ndn::Name("site").append(ndn::Name("%C1.Operator")))
     , conf(face, m_keyChain)
@@ -54,8 +54,8 @@
     , SITE_CERT_PATH(boost::filesystem::current_path() / std::string("site.cert"))
   {
     // Site cert
-    siteIdentity = addIdentity(siteIdentityName);
-    saveCertificate(siteIdentity, SITE_CERT_PATH.string());
+    siteIdentity = m_keyChain.createIdentity(siteIdentityName);
+    saveIdentityCert(siteIdentity, SITE_CERT_PATH.string());
 
     // Operator cert
     opIdentity = addSubCertificate(opIdentityName, siteIdentity);
@@ -68,11 +68,9 @@
 
     std::ifstream inputFile;
     inputFile.open(std::string("nlsr.conf"));
-
     BOOST_REQUIRE(inputFile.is_open());
 
     boost::property_tree::ptree pt;
-
     boost::property_tree::read_info(inputFile, pt);
     for (const auto& tn : pt) {
       if (tn.first == "security") {
@@ -85,7 +83,7 @@
     }
     inputFile.close();
 
-    addIdentity(conf.getRouterPrefix());
+    m_keyChain.createIdentity(conf.getRouterPrefix());
 
     this->advanceClocks(ndn::time::milliseconds(10));
 
diff --git a/tests/update/test-save-delete-prefix.cpp b/tests/update/test-save-delete-prefix.cpp
index c4db1bc..84612e4 100644
--- a/tests/update/test-save-delete-prefix.cpp
+++ b/tests/update/test-save-delete-prefix.cpp
@@ -20,18 +20,18 @@
  */
 
 #include "update/prefix-update-processor.hpp"
+#include "conf-parameter.hpp"
 #include "nlsr.hpp"
 
-#include "tests/control-commands.hpp"
+#include "tests/io-key-chain-fixture.hpp"
 #include "tests/test-common.hpp"
-#include "conf-parameter.hpp"
 
 #include <ndn-cxx/mgmt/nfd/control-response.hpp>
 #include <ndn-cxx/security/interest-signer.hpp>
-#include <ndn-cxx/security/pib/identity.hpp>
 #include <ndn-cxx/security/signing-helpers.hpp>
 
-#include <boost/filesystem.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
 #include <boost/property_tree/info_parser.hpp>
 
 namespace nlsr {
@@ -39,11 +39,11 @@
 
 namespace bpt = boost::property_tree;
 
-class PrefixSaveDeleteFixture : public UnitTestTimeFixture
+class PrefixSaveDeleteFixture : public IoKeyChainFixture
 {
 public:
   PrefixSaveDeleteFixture()
-    : face(m_ioService, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , siteIdentityName(ndn::Name("/edu/test-site"))
     , opIdentityName(ndn::Name("/edu/test-site").append(ndn::Name("%C1.Operator")))
     , testConfFile("/tmp/nlsr.conf.test")
@@ -60,8 +60,8 @@
     destination.close();
 
     conf.setConfFileNameDynamic(testConfFile);
-    siteIdentity = addIdentity(siteIdentityName);
-    saveCertificate(siteIdentity, SITE_CERT_PATH.string());
+    siteIdentity = m_keyChain.createIdentity(siteIdentityName);
+    saveIdentityCert(siteIdentity, SITE_CERT_PATH.string());
 
     // Operator cert
     opIdentity = addSubCertificate(opIdentityName, siteIdentity);
@@ -86,8 +86,8 @@
     inputFile.close();
 
     // Site cert
-    siteIdentity = addIdentity(siteIdentityName);
-    saveCertificate(siteIdentity, SITE_CERT_PATH.string());
+    siteIdentity = m_keyChain.createIdentity(siteIdentityName);
+    saveIdentityCert(siteIdentity, SITE_CERT_PATH.string());
 
     // Operator cert
     opIdentity = addSubCertificate(opIdentityName, siteIdentity);
@@ -98,7 +98,7 @@
     conf.loadCertToValidator(opIdentity.getDefaultKey().getDefaultCertificate());
 
     // Set the network so the LSA prefix is constructed
-    addIdentity(conf.getRouterPrefix());
+    m_keyChain.createIdentity(conf.getRouterPrefix());
 
     this->advanceClocks(ndn::time::milliseconds(10));
     face.sentInterests.clear();
diff --git a/tests/wscript b/tests/wscript
index 8371275..fe86136 100644
--- a/tests/wscript
+++ b/tests/wscript
@@ -1,7 +1,6 @@
 # -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-
 """
-Copyright (c) 2014-2019,  The University of Memphis
+Copyright (c) 2014-2022,  The University of Memphis
                           Regents of the University of California
 
 This file is part of NLSR (Named-data Link State Routing).
@@ -22,9 +21,6 @@
 top = '..'
 
 def build(bld):
-    if not bld.env.WITH_TESTS:
-        return
-
     bld.objects(target='unit-test-objects',
                 source=bld.path.ant_glob('**/*.cpp', excl=['main.cpp']),
                 use='nlsr-objects')