tests: refactor common test infrastructure and fixtures

Change-Id: I597c11130eefa2cc2846ee6655c85dc04f2f22ef
diff --git a/tests/benchmarks/timed-execute.hpp b/tests/benchmarks/timed-execute.hpp
index c0759e3..50bec30 100644
--- a/tests/benchmarks/timed-execute.hpp
+++ b/tests/benchmarks/timed-execute.hpp
@@ -19,8 +19,8 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_BENCHMARKS_TIMED_EXECUTE_HPP
-#define NDN_TESTS_BENCHMARKS_TIMED_EXECUTE_HPP
+#ifndef NDN_CXX_TESTS_BENCHMARKS_TIMED_EXECUTE_HPP
+#define NDN_CXX_TESTS_BENCHMARKS_TIMED_EXECUTE_HPP
 
 #include "ndn-cxx/util/time.hpp"
 
@@ -40,4 +40,4 @@
 } // namespace tests
 } // namespace ndn
 
-#endif // NDN_TESTS_BENCHMARKS_TIMED_EXECUTE_HPP
+#endif // NDN_CXX_TESTS_BENCHMARKS_TIMED_EXECUTE_HPP
diff --git a/tests/boost-test.hpp b/tests/boost-test.hpp
index 51e0973..a503391 100644
--- a/tests/boost-test.hpp
+++ b/tests/boost-test.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -19,8 +19,8 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_BOOST_TEST_HPP
-#define NDN_TESTS_BOOST_TEST_HPP
+#ifndef NDN_CXX_TESTS_BOOST_TEST_HPP
+#define NDN_CXX_TESTS_BOOST_TEST_HPP
 
 // suppress warnings from Boost.Test
 #pragma GCC system_header
@@ -29,4 +29,4 @@
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 
-#endif // NDN_TESTS_BOOST_TEST_HPP
+#endif // NDN_CXX_TESTS_BOOST_TEST_HPP
diff --git a/tests/identity-management-fixture.cpp b/tests/identity-management-fixture.cpp
deleted file mode 100644
index 0c95567..0000000
--- a/tests/identity-management-fixture.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2020 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 "tests/identity-management-fixture.hpp"
-
-#include "ndn-cxx/security/additional-description.hpp"
-#include "ndn-cxx/util/io.hpp"
-
-#include <boost/filesystem.hpp>
-
-namespace ndn {
-namespace tests {
-
-namespace v2 = security::v2;
-
-IdentityManagementBaseFixture::~IdentityManagementBaseFixture()
-{
-  boost::system::error_code ec;
-  for (const auto& certFile : m_certFiles) {
-    boost::filesystem::remove(certFile, ec); // ignore error
-  }
-}
-
-bool
-IdentityManagementBaseFixture::saveCertToFile(const 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:")
-{
-}
-
-security::Identity
-IdentityManagementFixture::addIdentity(const Name& identityName, const KeyParams& params)
-{
-  auto identity = m_keyChain.createIdentity(identityName, params);
-  m_identities.insert(identityName);
-  return identity;
-}
-
-bool
-IdentityManagementFixture::saveCertificate(const security::Identity& identity, const std::string& filename)
-{
-  try {
-    auto cert = identity.getDefaultKey().getDefaultCertificate();
-    return saveCertToFile(cert, filename);
-  }
-  catch (const security::Pib::Error&) {
-    return false;
-  }
-}
-
-security::Identity
-IdentityManagementFixture::addSubCertificate(const Name& subIdentityName,
-                                             const security::Identity& issuer, const KeyParams& params)
-{
-  auto subIdentity = addIdentity(subIdentityName, params);
-
-  v2::Certificate request = subIdentity.getDefaultKey().getDefaultCertificate();
-
-  request.setName(request.getKeyName().append("parent").appendVersion());
-
-  SignatureInfo info;
-  auto now = time::system_clock::now();
-  info.setValidityPeriod(security::ValidityPeriod(now, now + 7300_days));
-
-  v2::AdditionalDescription description;
-  description.set("type", "sub-certificate");
-  info.addCustomTlv(description.wireEncode());
-
-  m_keyChain.sign(request, signingByIdentity(issuer).setSignatureInfo(info));
-  m_keyChain.setDefaultCertificate(subIdentity.getDefaultKey(), request);
-
-  return subIdentity;
-}
-
-v2::Certificate
-IdentityManagementFixture::addCertificate(const security::Key& key, const std::string& issuer)
-{
-  Name certificateName = key.getName();
-  certificateName
-    .append(issuer)
-    .appendVersion();
-  v2::Certificate certificate;
-  certificate.setName(certificateName);
-
-  // set metainfo
-  certificate.setContentType(tlv::ContentType_Key);
-  certificate.setFreshnessPeriod(1_h);
-
-  // set content
-  certificate.setContent(key.getPublicKey().data(), key.getPublicKey().size());
-
-  // set signature-info
-  SignatureInfo info;
-  auto now = time::system_clock::now();
-  info.setValidityPeriod(security::ValidityPeriod(now, now + 10_days));
-
-  m_keyChain.sign(certificate, signingByKey(key).setSignatureInfo(info));
-  return certificate;
-}
-
-} // namespace tests
-} // namespace ndn
diff --git a/tests/identity-management-fixture.hpp b/tests/identity-management-fixture.hpp
deleted file mode 100644
index 7c0ffbd..0000000
--- a/tests/identity-management-fixture.hpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2020 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.
- */
-
-#ifndef NDN_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
-#define NDN_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
-
-#include "ndn-cxx/security/key-chain.hpp"
-#include "ndn-cxx/security/signing-helpers.hpp"
-
-#include "tests/test-home-fixture.hpp"
-
-#include <vector>
-
-namespace ndn {
-namespace tests {
-
-class IdentityManagementBaseFixture : public TestHomeFixture<DefaultPibDir>
-{
-public:
-  ~IdentityManagementBaseFixture();
-
-  bool
-  saveCertToFile(const Data& obj, const std::string& filename);
-
-protected:
-  std::set<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
-   */
-  security::Identity
-  addIdentity(const Name& identityName,
-              const KeyParams& params = security::v2::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 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
-   */
-  security::Identity
-  addSubCertificate(const Name& subIdentityName, const security::Identity& issuer,
-                    const KeyParams& params = security::v2::KeyChain::getDefaultKeyParams());
-
-  /**
-   * @brief Add a self-signed certificate to @p key with issuer ID @p issuer
-   */
-  security::v2::Certificate
-  addCertificate(const security::Key& key, const std::string& issuer);
-
-protected:
-  KeyChain m_keyChain;
-};
-
-} // namespace tests
-} // namespace ndn
-
-#endif // NDN_TESTS_IDENTITY_MANAGEMENT_FIXTURE_HPP
diff --git a/tests/integration/face.cpp b/tests/integration/face.cpp
index 1f5fc53..878b0cc 100644
--- a/tests/integration/face.cpp
+++ b/tests/integration/face.cpp
@@ -27,8 +27,8 @@
 #include "ndn-cxx/transport/unix-transport.hpp"
 #include "ndn-cxx/util/scheduler.hpp"
 
-#include "tests/identity-management-fixture.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 #include <stdio.h>
 #include <condition_variable>
@@ -64,7 +64,7 @@
 }
 
 template<typename TransportType>
-class FaceFixture : public IdentityManagementFixture
+class FaceFixture : public KeyChainFixture
 {
 protected:
   FaceFixture()
diff --git a/tests/key-chain-fixture.cpp b/tests/key-chain-fixture.cpp
new file mode 100644
index 0000000..e2d7a97
--- /dev/null
+++ b/tests/key-chain-fixture.cpp
@@ -0,0 +1,119 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2020 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 "tests/key-chain-fixture.hpp"
+
+#include "ndn-cxx/util/io.hpp"
+
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace tests {
+
+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
+  }
+}
+
+Certificate
+KeyChainFixture::makeCert(const Key& key, const std::string& issuer, const Key& signingKey)
+{
+  Certificate cert;
+  cert.setName(Name(key.getName())
+               .append(issuer)
+               .appendVersion());
+
+  // set metainfo
+  cert.setContentType(tlv::ContentType_Key);
+  cert.setFreshnessPeriod(1_h);
+
+  // set content
+  cert.setContent(key.getPublicKey().data(), key.getPublicKey().size());
+
+  // set signature info
+  ndn::SignatureInfo info;
+  auto now = time::system_clock::now();
+  info.setValidityPeriod(ValidityPeriod(now - 30_days, now + 30_days));
+
+  m_keyChain.sign(cert, signingByKey(signingKey ? signingKey : key).setSignatureInfo(info));
+  return cert;
+}
+
+bool
+KeyChainFixture::saveCert(const 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 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);
+}
+
+} // namespace tests
+} // namespace ndn
diff --git a/tests/key-chain-fixture.hpp b/tests/key-chain-fixture.hpp
new file mode 100644
index 0000000..7ed405b
--- /dev/null
+++ b/tests/key-chain-fixture.hpp
@@ -0,0 +1,97 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2020 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.
+ */
+
+#ifndef NDN_CXX_TESTS_KEY_CHAIN_FIXTURE_HPP
+#define NDN_CXX_TESTS_KEY_CHAIN_FIXTURE_HPP
+
+#include "ndn-cxx/security/key-chain.hpp"
+#include "ndn-cxx/security/signing-helpers.hpp"
+
+#include "tests/test-home-fixture.hpp"
+
+namespace ndn {
+namespace tests {
+
+/**
+ * @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 : public TestHomeFixture<DefaultPibDir>
+{
+protected:
+  using Certificate = ndn::security::Certificate;
+  using Identity    = ndn::security::Identity;
+  using Key         = ndn::security::Key;
+
+public:
+  /**
+   * @brief Creates and returns a certificate for a given key
+   * @param key The key for which to make a certificate
+   * @param issuer The IssuerId to include in the certificate name
+   * @param signingKey The key with which to sign the certificate; if not provided, the
+   *                   certificate will be self-signed
+   */
+  Certificate
+  makeCert(const Key& key, const std::string& issuer, const Key& signingKey = Key());
+
+  /**
+   * @brief Saves an NDN certificate to a file
+   * @return true if successful, false otherwise
+   */
+  bool
+  saveCert(const 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 Name& identityName, const std::string& filename,
+                   bool allowCreate = false);
+
+protected:
+  KeyChainFixture();
+
+  ~KeyChainFixture();
+
+protected:
+  ndn::KeyChain m_keyChain;
+
+private:
+  std::vector<std::string> m_certFiles;
+};
+
+} // namespace tests
+} // namespace ndn
+
+#endif // NDN_CXX_TESTS_KEY_CHAIN_FIXTURE_HPP
diff --git a/tests/make-interest-data.cpp b/tests/test-common.cpp
similarity index 97%
rename from tests/make-interest-data.cpp
rename to tests/test-common.cpp
index b4f47a0..7041406 100644
--- a/tests/make-interest-data.cpp
+++ b/tests/test-common.cpp
@@ -19,7 +19,7 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
diff --git a/tests/make-interest-data.hpp b/tests/test-common.hpp
similarity index 90%
rename from tests/make-interest-data.hpp
rename to tests/test-common.hpp
index fd2b042..f7f58a3 100644
--- a/tests/make-interest-data.hpp
+++ b/tests/test-common.hpp
@@ -19,12 +19,13 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_CXX_TESTS_MAKE_INTEREST_DATA_HPP
-#define NDN_CXX_TESTS_MAKE_INTEREST_DATA_HPP
+#ifndef NDN_CXX_TESTS_TEST_COMMON_HPP
+#define NDN_CXX_TESTS_TEST_COMMON_HPP
 
 #include "ndn-cxx/data.hpp"
 #include "ndn-cxx/interest.hpp"
 #include "ndn-cxx/lp/nack.hpp"
+#include "tests/boost-test.hpp"
 
 namespace ndn {
 namespace tests {
@@ -40,7 +41,7 @@
 /**
  * \brief Create a Data with a null (i.e., empty) signature
  *
- * If a real signature is desired, use IdentityManagementFixture and sign again with KeyChain.
+ * If a "real" signature is desired, use KeyChainFixture and sign again with `m_keyChain`.
  */
 shared_ptr<Data>
 makeData(const Name& name);
@@ -85,4 +86,4 @@
 } // namespace tests
 } // namespace ndn
 
-#endif // NDN_CXX_TESTS_MAKE_INTEREST_DATA_HPP
+#endif // NDN_CXX_TESTS_TEST_COMMON_HPP
diff --git a/tests/tests-pch.hpp b/tests/tests-pch.hpp
index f60e472..30e0fdc 100644
--- a/tests/tests-pch.hpp
+++ b/tests/tests-pch.hpp
@@ -19,8 +19,8 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_TESTS_PCH_HPP
-#define NDN_TESTS_TESTS_PCH_HPP
+#ifndef NDN_CXX_TESTS_TESTS_PCH_HPP
+#define NDN_CXX_TESTS_TESTS_PCH_HPP
 
 #include "ndn-cxx/impl/common-pch.hpp"
 
@@ -34,4 +34,4 @@
 #include <fstream>
 #include <boost/filesystem.hpp>
 
-#endif // NDN_TESTS_TESTS_PCH_HPP
+#endif // NDN_CXX_TESTS_TESTS_PCH_HPP
diff --git a/tests/unit/clock-fixture.cpp b/tests/unit/clock-fixture.cpp
new file mode 100644
index 0000000..3f543ff
--- /dev/null
+++ b/tests/unit/clock-fixture.cpp
@@ -0,0 +1,56 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2020 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 "tests/unit/clock-fixture.hpp"
+
+namespace ndn {
+namespace tests {
+
+ClockFixture::ClockFixture()
+  : m_steadyClock(make_shared<time::UnitTestSteadyClock>())
+  , m_systemClock(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 tests
+} // namespace ndn
diff --git a/tests/unit/clock-fixture.hpp b/tests/unit/clock-fixture.hpp
new file mode 100644
index 0000000..68dabbf
--- /dev/null
+++ b/tests/unit/clock-fixture.hpp
@@ -0,0 +1,85 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2020 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.
+ */
+
+#ifndef NDN_CXX_TESTS_UNIT_CLOCK_FIXTURE_HPP
+#define NDN_CXX_TESTS_UNIT_CLOCK_FIXTURE_HPP
+
+#include "ndn-cxx/util/time-unit-test-clock.hpp"
+
+namespace ndn {
+namespace tests {
+
+/** \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:
+  shared_ptr<time::UnitTestSteadyClock> m_steadyClock;
+  shared_ptr<time::UnitTestSystemClock> m_systemClock;
+};
+
+} // namespace tests
+} // namespace ndn
+
+#endif // NDN_CXX_TESTS_UNIT_CLOCK_FIXTURE_HPP
diff --git a/tests/unit/data.t.cpp b/tests/unit/data.t.cpp
index 69e0e69..64adf2f 100644
--- a/tests/unit/data.t.cpp
+++ b/tests/unit/data.t.cpp
@@ -31,7 +31,7 @@
 #include "ndn-cxx/util/string-helper.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 #include <boost/lexical_cast.hpp>
 
@@ -392,7 +392,7 @@
 
 BOOST_AUTO_TEST_SUITE_END() // Decode
 
-BOOST_FIXTURE_TEST_CASE(FullName, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(FullName, KeyChainFixture)
 {
   Data d(Name("/local/ndn/prefix"));
   d.setContentType(tlv::ContentType_Blob);
@@ -574,7 +574,7 @@
   BOOST_CHECK_THROW(d.setSignatureValue(nullptr), std::invalid_argument);
 }
 
-BOOST_FIXTURE_TEST_CASE(ExtractSignedRanges, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(ExtractSignedRanges, KeyChainFixture)
 {
   Data d1("/test/prefix");
   m_keyChain.sign(d1);
diff --git a/tests/unit/dummy-validator.hpp b/tests/unit/dummy-validator.hpp
index bb05167..be0adb3 100644
--- a/tests/unit/dummy-validator.hpp
+++ b/tests/unit/dummy-validator.hpp
@@ -19,8 +19,8 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_UNIT_DUMMY_VALIDATOR_HPP
-#define NDN_TESTS_UNIT_DUMMY_VALIDATOR_HPP
+#ifndef NDN_CXX_TESTS_UNIT_DUMMY_VALIDATOR_HPP
+#define NDN_CXX_TESTS_UNIT_DUMMY_VALIDATOR_HPP
 
 #include "ndn-cxx/security/validator.hpp"
 #include "ndn-cxx/security/validation-policy.hpp"
@@ -31,7 +31,7 @@
 
 /** \brief A validation policy for unit testing
  */
-class DummyValidationPolicy : public security::v2::ValidationPolicy
+class DummyValidationPolicy : public security::ValidationPolicy
 {
 public:
   /** \brief constructor
@@ -57,58 +57,58 @@
    *            its return value determines the validation result
    */
   void
-  setResultCallback(const function<bool(const Name&)>& cb)
+  setResultCallback(std::function<bool(const Name&)> cb)
   {
-    m_decide = cb;
+    m_decide = std::move(cb);
   }
 
 protected:
   void
-  checkPolicy(const Data& data, const shared_ptr<security::v2::ValidationState>& state,
+  checkPolicy(const Data& data, const shared_ptr<security::ValidationState>& state,
               const ValidationContinuation& continueValidation) override
   {
     if (m_decide(data.getName())) {
       continueValidation(nullptr, state);
     }
     else {
-      state->fail(security::v2::ValidationError::NO_ERROR);
+      state->fail(security::ValidationError::NO_ERROR);
     }
   }
 
   void
-  checkPolicy(const Interest& interest, const shared_ptr<security::v2::ValidationState>& state,
+  checkPolicy(const Interest& interest, const shared_ptr<security::ValidationState>& state,
               const ValidationContinuation& continueValidation) override
   {
     if (m_decide(interest.getName())) {
       continueValidation(nullptr, state);
     }
     else {
-      state->fail(security::v2::ValidationError::NO_ERROR);
+      state->fail(security::ValidationError::NO_ERROR);
     }
   }
 
 private:
-  function<bool(const Name&)> m_decide;
+  std::function<bool(const Name&)> m_decide;
 };
 
-class DummyValidator : public security::v2::Validator
+class DummyValidator : public security::Validator
 {
 public:
   explicit
   DummyValidator(bool shouldAccept = true)
-    : security::v2::Validator(make_unique<DummyValidationPolicy>(shouldAccept),
-                              make_unique<security::v2::CertificateFetcherOffline>())
+    : security::Validator(make_unique<DummyValidationPolicy>(shouldAccept),
+                          make_unique<security::CertificateFetcherOffline>())
   {
   }
 
   DummyValidationPolicy&
   getPolicy()
   {
-    return static_cast<DummyValidationPolicy&>(security::v2::Validator::getPolicy());
+    return static_cast<DummyValidationPolicy&>(security::Validator::getPolicy());
   }
 };
 
 } // namespace tests
 } // namespace ndn
 
-#endif // NDN_TESTS_UNIT_DUMMY_VALIDATOR_HPP
+#endif // NDN_CXX_TESTS_UNIT_DUMMY_VALIDATOR_HPP
diff --git a/tests/unit/face.t.cpp b/tests/unit/face.t.cpp
index b368667..f7c6132 100644
--- a/tests/unit/face.t.cpp
+++ b/tests/unit/face.t.cpp
@@ -26,9 +26,8 @@
 #include "ndn-cxx/util/dummy-client-face.hpp"
 #include "ndn-cxx/util/scheduler.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/test-common.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 
 #include <boost/logic/tribool.hpp>
 
@@ -41,11 +40,11 @@
 struct NoPrefixRegReply;
 
 template<typename PrefixRegReply = WantPrefixRegReply>
-class FaceFixture : public IdentityManagementTimeFixture
+class FaceFixture : public IoKeyChainFixture
 {
 protected:
   FaceFixture()
-    : face(io, m_keyChain, {true, !std::is_same<PrefixRegReply, NoPrefixRegReply>::value})
+    : face(m_io, m_keyChain, {true, !std::is_same<PrefixRegReply, NoPrefixRegReply>::value})
   {
     static_assert(std::is_same<PrefixRegReply, WantPrefixRegReply>::value ||
                   std::is_same<PrefixRegReply, NoPrefixRegReply>::value, "");
@@ -279,7 +278,7 @@
 
 BOOST_AUTO_TEST_CASE(DestroyWithPendingInterest)
 {
-  auto face2 = make_unique<DummyClientFace>(io, m_keyChain);
+  auto face2 = make_unique<DummyClientFace>(m_io, m_keyChain);
   face2->expressInterest(*makeInterest("/Hello/World", false, 50_ms),
                          nullptr, nullptr, nullptr);
   advanceClocks(50_ms, 2);
@@ -304,7 +303,7 @@
   advanceClocks(200_ms, 5);
 
   // cancel after destructing face
-  auto face2 = make_unique<DummyClientFace>(io, m_keyChain);
+  auto face2 = make_unique<DummyClientFace>(m_io, m_keyChain);
   auto hdl2 = face2->expressInterest(*makeInterest("/Hello/World", true, 50_ms),
                                      bind([] { BOOST_FAIL("Unexpected data"); }),
                                      bind([] { BOOST_FAIL("Unexpected nack"); }),
@@ -555,7 +554,7 @@
   BOOST_CHECK(!doUnreg());
 
   // cancel after destructing face
-  auto face2 = make_unique<DummyClientFace>(io, m_keyChain);
+  auto face2 = make_unique<DummyClientFace>(m_io, m_keyChain);
   hdl = face2->registerPrefix("/Hello/World/2", nullptr,
                               bind([] { BOOST_FAIL("Unexpected registerPrefix failure"); }));
   advanceClocks(1_ms);
@@ -565,7 +564,7 @@
   advanceClocks(1_ms);
 
   // unregister after destructing face
-  auto face3 = make_unique<DummyClientFace>(io, m_keyChain);
+  auto face3 = make_unique<DummyClientFace>(m_io, m_keyChain);
   hdl = face3->registerPrefix("/Hello/World/3", nullptr,
                               bind([] { BOOST_FAIL("Unexpected registerPrefix failure"); }));
   advanceClocks(1_ms);
@@ -811,7 +810,7 @@
   BOOST_CHECK_EQUAL(hit, 1);
 
   // cancel after destructing face
-  auto face2 = make_unique<DummyClientFace>(io, m_keyChain);
+  auto face2 = make_unique<DummyClientFace>(m_io, m_keyChain);
   InterestFilterHandle hdl2 = face2->setInterestFilter("/Hello/World/2", nullptr);
   advanceClocks(1_ms);
   face2.reset();
@@ -841,10 +840,10 @@
 
 BOOST_AUTO_TEST_CASE(DestroyWithoutProcessEvents) // Bug 3248
 {
-  auto face2 = make_unique<Face>(io);
+  auto face2 = make_unique<Face>(m_io);
   face2.reset();
 
-  io.poll(); // should not crash
+  m_io.poll(); // should not crash
 
   // avoid "test case [...] did not check any assertions" message from Boost.Test
   BOOST_CHECK(true);
@@ -859,21 +858,21 @@
   const std::string PATH = "build/keys-with-default-tpm";
 };
 
-BOOST_FIXTURE_TEST_CASE(FaceTransport, IdentityManagementTimeFixture)
+BOOST_FIXTURE_TEST_CASE(FaceTransport, IoKeyChainFixture)
 {
   BOOST_CHECK(Face().getTransport() != nullptr);
 
   BOOST_CHECK(Face(shared_ptr<Transport>()).getTransport() != nullptr);
-  BOOST_CHECK(Face(shared_ptr<Transport>(), io).getTransport() != nullptr);
-  BOOST_CHECK(Face(shared_ptr<Transport>(), io, m_keyChain).getTransport() != nullptr);
+  BOOST_CHECK(Face(shared_ptr<Transport>(), m_io).getTransport() != nullptr);
+  BOOST_CHECK(Face(shared_ptr<Transport>(), m_io, m_keyChain).getTransport() != nullptr);
 
   auto transport = make_shared<TcpTransport>("localhost", "6363"); // no real io operations will be scheduled
   BOOST_CHECK(Face(transport).getTransport() == transport);
-  BOOST_CHECK(Face(transport, io).getTransport() == transport);
-  BOOST_CHECK(Face(transport, io, m_keyChain).getTransport() == transport);
+  BOOST_CHECK(Face(transport, m_io).getTransport() == transport);
+  BOOST_CHECK(Face(transport, m_io, m_keyChain).getTransport() == transport);
 }
 
-class WithEnv : private IdentityManagementTimeFixture
+class WithEnv
 {
 public:
   WithEnv()
@@ -887,13 +886,13 @@
   void
   configure(const std::string& faceUri)
   {
-    setenv("NDN_CLIENT_TRANSPORT", faceUri.c_str(), true);
+    setenv("NDN_CLIENT_TRANSPORT", faceUri.data(), true);
   }
 
   ~WithEnv()
   {
     if (!m_oldTransport.empty()) {
-      setenv("NDN_CLIENT_TRANSPORT", m_oldTransport.c_str(), true);
+      setenv("NDN_CLIENT_TRANSPORT", m_oldTransport.data(), true);
     }
     else {
       unsetenv("NDN_CLIENT_TRANSPORT");
diff --git a/tests/unit/ims/in-memory-storage-fifo.t.cpp b/tests/unit/ims/in-memory-storage-fifo.t.cpp
index b188797..bdf86ea 100644
--- a/tests/unit/ims/in-memory-storage-fifo.t.cpp
+++ b/tests/unit/ims/in-memory-storage-fifo.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,8 +21,7 @@
 
 #include "ndn-cxx/ims/in-memory-storage-fifo.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
diff --git a/tests/unit/ims/in-memory-storage-lfu.t.cpp b/tests/unit/ims/in-memory-storage-lfu.t.cpp
index 8756856..17aa9a6 100644
--- a/tests/unit/ims/in-memory-storage-lfu.t.cpp
+++ b/tests/unit/ims/in-memory-storage-lfu.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,8 +21,7 @@
 
 #include "ndn-cxx/ims/in-memory-storage-lfu.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
diff --git a/tests/unit/ims/in-memory-storage-lru.t.cpp b/tests/unit/ims/in-memory-storage-lru.t.cpp
index aeeb846..cbf2bab 100644
--- a/tests/unit/ims/in-memory-storage-lru.t.cpp
+++ b/tests/unit/ims/in-memory-storage-lru.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,8 +21,7 @@
 
 #include "ndn-cxx/ims/in-memory-storage-lru.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
diff --git a/tests/unit/ims/in-memory-storage-persistent.t.cpp b/tests/unit/ims/in-memory-storage-persistent.t.cpp
index 3758cc2..d0cabf9 100644
--- a/tests/unit/ims/in-memory-storage-persistent.t.cpp
+++ b/tests/unit/ims/in-memory-storage-persistent.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,8 +21,7 @@
 
 #include "ndn-cxx/ims/in-memory-storage-persistent.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
diff --git a/tests/unit/ims/in-memory-storage.t.cpp b/tests/unit/ims/in-memory-storage.t.cpp
index 737bb0e..594837b 100644
--- a/tests/unit/ims/in-memory-storage.t.cpp
+++ b/tests/unit/ims/in-memory-storage.t.cpp
@@ -26,9 +26,8 @@
 #include "ndn-cxx/ims/in-memory-storage-persistent.hpp"
 #include "ndn-cxx/util/sha256.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
-#include "tests/unit/unit-test-time-fixture.hpp"
+#include "tests/test-common.hpp"
+#include "tests/unit/io-fixture.hpp"
 
 #include <boost/mpl/vector.hpp>
 
@@ -120,7 +119,7 @@
 
   shared_ptr<Interest> interest = makeInterest(name);
 
-  shared_ptr<const Data> found = ims.find(*interest);
+  auto found = ims.find(*interest);
   BOOST_CHECK(found != nullptr);
   BOOST_CHECK_EQUAL(data->getName(), found->getName());
 }
@@ -136,9 +135,8 @@
   Name name2("/not/find");
   shared_ptr<Interest> interest = makeInterest(name2);
 
-  shared_ptr<const Data> found = ims.find(*interest);
-
-  BOOST_CHECK_EQUAL(found.get(), static_cast<const Data*>(0));
+  auto found = ims.find(*interest);
+  BOOST_CHECK(found == nullptr);
 }
 
 BOOST_AUTO_TEST_CASE_TEMPLATE(InsertAndFindByName, T, InMemoryStorages)
@@ -150,7 +148,7 @@
   shared_ptr<Data> data = makeData(name);
   ims.insert(*data);
 
-  shared_ptr<const Data> found = ims.find(name);
+  auto found = ims.find(name);
   BOOST_CHECK(found != nullptr);
   BOOST_CHECK_EQUAL(data->getName(), found->getName());
 }
@@ -164,7 +162,7 @@
   shared_ptr<Data> data = makeData(name);
   ims.insert(*data);
 
-  shared_ptr<const Data> found = ims.find(data->getFullName());
+  auto found = ims.find(data->getFullName());
   BOOST_CHECK(found != nullptr);
   BOOST_CHECK_EQUAL(data->getFullName(), found->getFullName());
 }
@@ -179,7 +177,7 @@
 
   Name name2("/not/find");
 
-  shared_ptr<const Data> found = ims.find(name2);
+  auto found = ims.find(name2);
   BOOST_CHECK(found == nullptr);
 }
 
@@ -199,7 +197,7 @@
   data2->setContent(reinterpret_cast<const uint8_t*>(&content2), sizeof(content2));
   signData(data2);
 
-  shared_ptr<const Data> found = ims.find(data2->getFullName());
+  auto found = ims.find(data2->getFullName());
   BOOST_CHECK(found == nullptr);
 }
 
@@ -444,14 +442,9 @@
 }
 
 // Find function is implemented at the base case, so it's sufficient to test for one derived class.
-class FindFixture : public tests::UnitTestTimeFixture
+class FindFixture : public IoFixture
 {
 protected:
-  FindFixture()
-    : m_ims(io)
-  {
-  }
-
   Name
   insert(uint32_t id, const Name& name,
          const std::function<void(Data&)>& modifyData = nullptr,
@@ -480,8 +473,8 @@
   uint32_t
   find()
   {
-    shared_ptr<const Data> found = m_ims.find(*m_interest);
-    if (found == 0) {
+    auto found = m_ims.find(*m_interest);
+    if (found == nullptr) {
       return 0;
     }
     const Block& content = found->getContent();
@@ -494,7 +487,7 @@
   }
 
 protected:
-  InMemoryStoragePersistent m_ims;
+  InMemoryStoragePersistent m_ims{m_io};
   shared_ptr<Interest> m_interest;
 };
 
diff --git a/tests/unit/interest-filter.t.cpp b/tests/unit/interest-filter.t.cpp
index f802c1d..12aba0a 100644
--- a/tests/unit/interest-filter.t.cpp
+++ b/tests/unit/interest-filter.t.cpp
@@ -24,8 +24,7 @@
 #include "ndn-cxx/encoding/buffer-stream.hpp"
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
diff --git a/tests/unit/interest.t.cpp b/tests/unit/interest.t.cpp
index 2887c99..e5c7d32 100644
--- a/tests/unit/interest.t.cpp
+++ b/tests/unit/interest.t.cpp
@@ -22,8 +22,7 @@
 #include "ndn-cxx/interest.hpp"
 #include "ndn-cxx/data.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
diff --git a/tests/unit/transport/transport-fixture.hpp b/tests/unit/io-fixture.hpp
similarity index 67%
rename from tests/unit/transport/transport-fixture.hpp
rename to tests/unit/io-fixture.hpp
index 6c84fd1..1c872c4 100644
--- a/tests/unit/transport/transport-fixture.hpp
+++ b/tests/unit/io-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -19,31 +19,37 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_UNIT_TRANSPORT_TRANSPORT_FIXTURE_HPP
-#define NDN_TESTS_UNIT_TRANSPORT_TRANSPORT_FIXTURE_HPP
+#ifndef NDN_CXX_TESTS_UNIT_IO_FIXTURE_HPP
+#define NDN_CXX_TESTS_UNIT_IO_FIXTURE_HPP
 
-#include "ndn-cxx/util/config-file.hpp"
+#include "tests/unit/clock-fixture.hpp"
 
-#include "tests/unit/test-home-env-saver.hpp"
+#include <boost/asio/io_service.hpp>
 
 namespace ndn {
 namespace tests {
 
-class TransportFixture : public TestHomeEnvSaver
+class IoFixture : public ClockFixture
 {
-public:
+private:
   void
-  initializeConfig(const char* path)
+  afterTick() final
   {
-    setenv("TEST_HOME", path, 1);
-    m_config = make_unique<ConfigFile>();
+    if (m_io.stopped()) {
+#if BOOST_VERSION >= 106600
+      m_io.restart();
+#else
+      m_io.reset();
+#endif
+    }
+    m_io.poll();
   }
 
 protected:
-  unique_ptr<ConfigFile> m_config;
+  boost::asio::io_service m_io;
 };
 
 } // namespace tests
 } // namespace ndn
 
-#endif // NDN_TESTS_UNIT_TRANSPORT_TRANSPORT_FIXTURE_HPP
+#endif // NDN_CXX_TESTS_UNIT_IO_FIXTURE_HPP
diff --git a/tests/unit/identity-management-time-fixture.hpp b/tests/unit/io-key-chain-fixture.hpp
similarity index 68%
rename from tests/unit/identity-management-time-fixture.hpp
rename to tests/unit/io-key-chain-fixture.hpp
index 6bff890..2df51b1 100644
--- a/tests/unit/identity-management-time-fixture.hpp
+++ b/tests/unit/io-key-chain-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -19,21 +19,20 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_UNIT_IDENTITY_MANAGEMENT_TIME_FIXTURE_HPP
-#define NDN_TESTS_UNIT_IDENTITY_MANAGEMENT_TIME_FIXTURE_HPP
+#ifndef NDN_CXX_TESTS_UNIT_IO_KEY_CHAIN_FIXTURE_HPP
+#define NDN_CXX_TESTS_UNIT_IO_KEY_CHAIN_FIXTURE_HPP
 
-#include "tests/identity-management-fixture.hpp"
-#include "tests/unit/unit-test-time-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
+#include "tests/unit/io-fixture.hpp"
 
 namespace ndn {
 namespace tests {
 
-class IdentityManagementTimeFixture : public UnitTestTimeFixture
-                                    , public IdentityManagementFixture
+class IoKeyChainFixture : public IoFixture, public KeyChainFixture
 {
 };
 
 } // namespace tests
 } // namespace ndn
 
-#endif // NDN_TESTS_UNIT_IDENTITY_MANAGEMENT_TIME_FIXTURE_HPP
+#endif // NDN_CXX_TESTS_UNIT_IO_KEY_CHAIN_FIXTURE_HPP
diff --git a/tests/unit/link.t.cpp b/tests/unit/link.t.cpp
index ef85f9f..1042d35 100644
--- a/tests/unit/link.t.cpp
+++ b/tests/unit/link.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,8 +21,7 @@
 
 #include "ndn-cxx/link.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
diff --git a/tests/unit/lp/packet.t.cpp b/tests/unit/lp/packet.t.cpp
index e5a9cdd..5f750c3 100644
--- a/tests/unit/lp/packet.t.cpp
+++ b/tests/unit/lp/packet.t.cpp
@@ -22,9 +22,8 @@
 #include "ndn-cxx/lp/packet.hpp"
 #include "ndn-cxx/prefix-announcement.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace lp {
@@ -428,7 +427,7 @@
   BOOST_CHECK_THROW(packet.wireDecode(wire), Packet::Error);
 }
 
-BOOST_FIXTURE_TEST_CASE(DecodePrefixAnnouncement, ndn::tests::IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(DecodePrefixAnnouncement, ndn::tests::KeyChainFixture)
 {
   // Construct Data which prefix announcement is attached to
   auto data0 = ndn::tests::makeData("/edu/ua/cs/news/index.html");
diff --git a/tests/unit/lp/prefix-announcement-header.t.cpp b/tests/unit/lp/prefix-announcement-header.t.cpp
index 3cccdb7..a107eb5 100644
--- a/tests/unit/lp/prefix-announcement-header.t.cpp
+++ b/tests/unit/lp/prefix-announcement-header.t.cpp
@@ -23,14 +23,14 @@
 #include "ndn-cxx/lp/tlv.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 namespace ndn {
 namespace lp {
 namespace tests {
 
 BOOST_AUTO_TEST_SUITE(Lp)
-BOOST_FIXTURE_TEST_SUITE(TestPrefixAnnouncementHeader, ndn::tests::IdentityManagementFixture)
+BOOST_FIXTURE_TEST_SUITE(TestPrefixAnnouncementHeader, ndn::tests::KeyChainFixture)
 
 BOOST_AUTO_TEST_CASE(EncodeDecode)
 {
diff --git a/tests/unit/metadata-object.t.cpp b/tests/unit/metadata-object.t.cpp
index 632e15f..7aae5cf 100644
--- a/tests/unit/metadata-object.t.cpp
+++ b/tests/unit/metadata-object.t.cpp
@@ -22,12 +22,12 @@
 #include "ndn-cxx/metadata-object.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 namespace ndn {
 namespace tests {
 
-class MetadataObjectFixture : public IdentityManagementFixture
+class MetadataObjectFixture : public KeyChainFixture
 {
 public:
   MetadataObjectFixture()
diff --git a/tests/unit/mgmt/dispatcher.t.cpp b/tests/unit/mgmt/dispatcher.t.cpp
index 7fa74e5..79d3dd3 100644
--- a/tests/unit/mgmt/dispatcher.t.cpp
+++ b/tests/unit/mgmt/dispatcher.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,9 +23,8 @@
 #include "ndn-cxx/mgmt/nfd/control-parameters.hpp"
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/test-common.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 
 namespace ndn {
 namespace mgmt {
@@ -33,11 +32,11 @@
 
 using namespace ndn::tests;
 
-class DispatcherFixture : public IdentityManagementTimeFixture
+class DispatcherFixture : public IoKeyChainFixture
 {
 public:
   DispatcherFixture()
-    : face(io, m_keyChain, {true, true})
+    : face(m_io, m_keyChain, {true, true})
     , dispatcher(face, m_keyChain, security::SigningInfo())
     , storage(dispatcher.m_storage)
   {
diff --git a/tests/unit/mgmt/nfd/controller-fixture.hpp b/tests/unit/mgmt/nfd/controller-fixture.hpp
index c210fcf..77c7620 100644
--- a/tests/unit/mgmt/nfd/controller-fixture.hpp
+++ b/tests/unit/mgmt/nfd/controller-fixture.hpp
@@ -19,15 +19,15 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_UNIT_MGMT_NFD_CONTROLLER_FIXTURE_HPP
-#define NDN_TESTS_UNIT_MGMT_NFD_CONTROLLER_FIXTURE_HPP
+#ifndef NDN_CXX_TESTS_UNIT_MGMT_NFD_CONTROLLER_FIXTURE_HPP
+#define NDN_CXX_TESTS_UNIT_MGMT_NFD_CONTROLLER_FIXTURE_HPP
 
 #include "ndn-cxx/mgmt/nfd/controller.hpp"
 #include "ndn-cxx/security/certificate-fetcher-offline.hpp"
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
 #include "tests/unit/dummy-validator.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 
 namespace ndn {
 namespace nfd {
@@ -35,18 +35,17 @@
 
 using namespace ndn::tests;
 
-class ControllerFixture : public IdentityManagementTimeFixture
+class ControllerFixture : public IoKeyChainFixture
 {
 protected:
   ControllerFixture()
-    : face(io, m_keyChain)
+    : face(m_io, m_keyChain)
     , m_validator(true)
     , controller(face, m_keyChain, m_validator)
     , commandFailCallback(bind(&ControllerFixture::recordCommandFail, this, _1))
     , datasetFailCallback(bind(&ControllerFixture::recordDatasetFail, this, _1, _2))
   {
-    Name identityName("/localhost/ControllerFixture");
-    m_keyChain.setDefaultIdentity(this->addIdentity(identityName));
+    m_keyChain.setDefaultIdentity(m_keyChain.createIdentity("/localhost/ControllerFixture"));
   }
 
   /** \brief controls whether Controller's validator should accept or reject validation requests
@@ -86,4 +85,4 @@
 } // namespace nfd
 } // namespace ndn
 
-#endif // NDN_TESTS_UNIT_MGMT_NFD_CONTROLLER_FIXTURE_HPP
+#endif // NDN_CXX_TESTS_UNIT_MGMT_NFD_CONTROLLER_FIXTURE_HPP
diff --git a/tests/unit/mgmt/nfd/controller.t.cpp b/tests/unit/mgmt/nfd/controller.t.cpp
index 01ff767..b0a5838 100644
--- a/tests/unit/mgmt/nfd/controller.t.cpp
+++ b/tests/unit/mgmt/nfd/controller.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,8 +22,7 @@
 #include "ndn-cxx/mgmt/nfd/controller.hpp"
 #include "ndn-cxx/mgmt/nfd/control-response.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 #include "tests/unit/mgmt/nfd/controller-fixture.hpp"
 
 namespace ndn {
@@ -65,8 +64,8 @@
 };
 
 // This test suite focuses on ControlCommand functionality of Controller.
-// Individual commands are tested in nfd-control-command.t.cpp
-// StatusDataset functionality is tested in nfd-status-dataset.t.cpp
+// Individual commands are tested in control-command.t.cpp
+// StatusDataset functionality is tested in status-dataset.t.cpp
 BOOST_FIXTURE_TEST_SUITE(TestController, CommandFixture)
 
 static ControlParameters
diff --git a/tests/unit/mgmt/nfd/status-dataset.t.cpp b/tests/unit/mgmt/nfd/status-dataset.t.cpp
index aac874b..44fca44 100644
--- a/tests/unit/mgmt/nfd/status-dataset.t.cpp
+++ b/tests/unit/mgmt/nfd/status-dataset.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,8 +22,7 @@
 #include "ndn-cxx/mgmt/nfd/status-dataset.hpp"
 #include "ndn-cxx/mgmt/nfd/controller.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 #include "tests/unit/mgmt/nfd/controller-fixture.hpp"
 
 namespace ndn {
diff --git a/tests/unit/mgmt/status-dataset-context.t.cpp b/tests/unit/mgmt/status-dataset-context.t.cpp
index 6ea594e..c46292c 100644
--- a/tests/unit/mgmt/status-dataset-context.t.cpp
+++ b/tests/unit/mgmt/status-dataset-context.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,8 +21,7 @@
 
 #include "ndn-cxx/mgmt/status-dataset-context.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace mgmt {
diff --git a/tests/unit/net/collect-netifs.cpp b/tests/unit/net/collect-netifs.cpp
deleted file mode 100644
index fe866af..0000000
--- a/tests/unit/net/collect-netifs.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 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 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 "tests/unit/net/collect-netifs.hpp"
-#include "ndn-cxx/net/network-monitor.hpp"
-
-#include <boost/asio/io_service.hpp>
-
-namespace ndn {
-namespace net {
-namespace tests {
-
-std::vector<shared_ptr<const NetworkInterface>>
-collectNetworkInterfaces(bool allowCached)
-{
-  static optional<std::vector<shared_ptr<const NetworkInterface>>> cached;
-
-  if (!allowCached || !cached) {
-    boost::asio::io_service io;
-    NetworkMonitor netmon(io);
-
-    if (netmon.getCapabilities() & NetworkMonitor::CAP_ENUM) {
-      netmon.onEnumerationCompleted.connect([&io] { io.stop(); });
-      io.run();
-      io.reset();
-    }
-    cached = netmon.listNetworkInterfaces();
-  }
-
-  return *cached;
-}
-
-} // namespace tests
-} // namespace net
-} // namespace ndn
diff --git a/tests/unit/net/collect-netifs.hpp b/tests/unit/net/collect-netifs.hpp
deleted file mode 100644
index cc104f6..0000000
--- a/tests/unit/net/collect-netifs.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 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 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.
- */
-
-#ifndef NDN_TESTS_UNIT_NET_COLLECT_NETIFS_HPP
-#define NDN_TESTS_UNIT_NET_COLLECT_NETIFS_HPP
-
-#include "ndn-cxx/net/network-interface.hpp"
-
-#include <vector>
-
-namespace ndn {
-namespace net {
-namespace tests {
-
-/** \brief Collect information about network interfaces
- *  \param allowCached if true, previously collected information can be returned
- *  \note This function is blocking if \p allowCached is false or no previous information exists
- */
-std::vector<shared_ptr<const NetworkInterface>>
-collectNetworkInterfaces(bool allowCached = true);
-
-} // namespace tests
-} // namespace net
-} // namespace ndn
-
-#endif // NDN_TESTS_UNIT_NET_COLLECT_NETIFS_HPP
diff --git a/tests/unit/net/face-uri.t.cpp b/tests/unit/net/face-uri.t.cpp
index 2b99470..c8f7d16 100644
--- a/tests/unit/net/face-uri.t.cpp
+++ b/tests/unit/net/face-uri.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California,
+ * Copyright (c) 2013-2020 Regents of the University of California,
  *                         Arizona Board of Regents,
  *                         Colorado State University,
  *                         University Pierre & Marie Curie, Sorbonne University,
@@ -26,9 +26,10 @@
  */
 
 #include "ndn-cxx/net/face-uri.hpp"
+#include "ndn-cxx/net/network-interface.hpp"
+#include "ndn-cxx/net/network-monitor.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/net/collect-netifs.hpp"
 #include "tests/unit/net/network-configuration-detector.hpp"
 
 namespace ndn {
@@ -37,9 +38,30 @@
 BOOST_AUTO_TEST_SUITE(Net)
 BOOST_AUTO_TEST_SUITE(TestFaceUri)
 
-class CanonizeFixture : noncopyable
+class CanonizeFixture
 {
 protected:
+  CanonizeFixture()
+  {
+    static const auto netifs = [this] {
+      net::NetworkMonitor netmon(m_io);
+      if (netmon.getCapabilities() & net::NetworkMonitor::CAP_ENUM) {
+        netmon.onEnumerationCompleted.connect([this] { m_io.stop(); });
+        m_io.run();
+#if BOOST_VERSION >= 106600
+        m_io.restart();
+#else
+        m_io.reset();
+#endif
+      }
+      return netmon.listNetworkInterfaces();
+    }();
+
+    if (!netifs.empty()) {
+      m_netif = netifs.front();
+    }
+  }
+
   void
   addTest(const std::string& request, bool shouldSucceed, const std::string& expectedUri)
   {
@@ -101,6 +123,9 @@
     BOOST_CHECK_MESSAGE(!tc->m_shouldSucceed, tc->m_message);
   }
 
+protected:
+  shared_ptr<const net::NetworkInterface> m_netif;
+
 private:
   boost::asio::io_service m_io;
   ssize_t m_nPending = 0;
@@ -205,11 +230,9 @@
   BOOST_CHECK_EQUAL(FaceUri("udp4://[2001:db8::1]:6363").isCanonical(), false);
   BOOST_CHECK_EQUAL(FaceUri("udp6://192.0.2.1:6363").isCanonical(), false);
 
-  const auto& networkInterfaces = ndn::net::tests::collectNetworkInterfaces();
-  if (!networkInterfaces.empty()) {
-    const auto& netif = networkInterfaces.front();
-    auto name = netif->getName();
-    auto index = to_string(netif->getIndex());
+  if (m_netif) {
+    auto name = m_netif->getName();
+    auto index = to_string(m_netif->getIndex());
 
     BOOST_CHECK_EQUAL(FaceUri("udp6://[fe80::1%" + name + "]:6363").isCanonical(), true);
     BOOST_CHECK_EQUAL(FaceUri("udp6://[fe80::1%" + index + "]:6363").isCanonical(), false);
@@ -270,11 +293,9 @@
   // IPv4 used with udp6 protocol - not canonical
   addTest("udp6://192.0.2.1:6363", false, "");
 
-  const auto& networkInterfaces = ndn::net::tests::collectNetworkInterfaces();
-  if (!networkInterfaces.empty()) {
-    const auto& netif = networkInterfaces.front();
-    auto name = netif->getName();
-    auto index = to_string(netif->getIndex());
+  if (m_netif) {
+    auto name = m_netif->getName();
+    auto index = to_string(m_netif->getIndex());
 
     addTest("udp6://[fe80::1068:dddb:fe26:fe3f%25" + name + "]:6363", true,
             "udp6://[fe80::1068:dddb:fe26:fe3f%" + name + "]:6363");
@@ -342,11 +363,9 @@
   BOOST_CHECK_EQUAL(FaceUri("tcp4://[2001:db8::1]:6363").isCanonical(), false);
   BOOST_CHECK_EQUAL(FaceUri("tcp6://192.0.2.1:6363").isCanonical(), false);
 
-  const auto& networkInterfaces = ndn::net::tests::collectNetworkInterfaces();
-  if (!networkInterfaces.empty()) {
-    const auto& netif = networkInterfaces.front();
-    auto name = netif->getName();
-    auto index = to_string(netif->getIndex());
+  if (m_netif) {
+    auto name = m_netif->getName();
+    auto index = to_string(m_netif->getIndex());
 
     BOOST_CHECK_EQUAL(FaceUri("tcp6://[fe80::1%" + name + "]:6363").isCanonical(), true);
     BOOST_CHECK_EQUAL(FaceUri("tcp6://[fe80::1%" + index + "]:6363").isCanonical(), false);
@@ -380,11 +399,9 @@
   // IPv6 used with tcp4 protocol - not canonical
   addTest("tcp4://[2001:db8::1]:6363", false, "");
 
-  const auto& networkInterfaces = ndn::net::tests::collectNetworkInterfaces();
-  if (!networkInterfaces.empty()) {
-    const auto& netif = networkInterfaces.front();
-    auto name = netif->getName();
-    auto index = to_string(netif->getIndex());
+  if (m_netif) {
+    auto name = m_netif->getName();
+    auto index = to_string(m_netif->getIndex());
 
     addTest("tcp6://[fe80::1068:dddb:fe26:fe3f%25" + name + "]:6363", true,
             "tcp6://[fe80::1068:dddb:fe26:fe3f%" + name + "]:6363");
diff --git a/tests/unit/prefix-announcement.t.cpp b/tests/unit/prefix-announcement.t.cpp
index 03fa7f9..d154484 100644
--- a/tests/unit/prefix-announcement.t.cpp
+++ b/tests/unit/prefix-announcement.t.cpp
@@ -22,9 +22,8 @@
 #include "ndn-cxx/prefix-announcement.hpp"
 #include "ndn-cxx/encoding/tlv-nfd.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 namespace ndn {
 namespace tests {
@@ -163,7 +162,7 @@
   });
 }
 
-BOOST_FIXTURE_TEST_CASE(EncodeEmpty, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(EncodeEmpty, KeyChainFixture)
 {
   PrefixAnnouncement pa;
   BOOST_CHECK(!pa.getData());
@@ -185,7 +184,7 @@
   BOOST_CHECK_EQUAL(pa, decoded);
 }
 
-BOOST_FIXTURE_TEST_CASE(EncodeNoValidity, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(EncodeNoValidity, KeyChainFixture)
 {
   PrefixAnnouncement pa;
   pa.setAnnouncedName("/net/example");
@@ -209,7 +208,7 @@
   BOOST_CHECK_EQUAL(pa, decoded);
 }
 
-BOOST_FIXTURE_TEST_CASE(EncodeWithValidity, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(EncodeWithValidity, KeyChainFixture)
 {
   PrefixAnnouncement pa;
   pa.setAnnouncedName("/net/example");
diff --git a/tests/unit/security/certificate-bundle-fetcher.t.cpp b/tests/unit/security/certificate-bundle-fetcher.t.cpp
index 1d0cee9..0c300b7 100644
--- a/tests/unit/security/certificate-bundle-fetcher.t.cpp
+++ b/tests/unit/security/certificate-bundle-fetcher.t.cpp
@@ -23,8 +23,7 @@
 #include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
 #include "ndn-cxx/util/regex/regex-pattern-list-matcher.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 #include "tests/unit/security/validator-fixture.hpp"
 
 namespace ndn {
diff --git a/tests/unit/security/certificate-cache.t.cpp b/tests/unit/security/certificate-cache.t.cpp
index 65614ac..7d60506 100644
--- a/tests/unit/security/certificate-cache.t.cpp
+++ b/tests/unit/security/certificate-cache.t.cpp
@@ -22,22 +22,23 @@
 #include "ndn-cxx/security/certificate-cache.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
+#include "tests/unit/clock-fixture.hpp"
 
 namespace ndn {
 namespace security {
 inline namespace v2 {
 namespace tests {
 
-BOOST_AUTO_TEST_SUITE(Security)
+using namespace ndn::tests;
 
-class CertificateCacheFixture : public ndn::tests::IdentityManagementTimeFixture
+class CertificateCacheFixture : public ClockFixture, public KeyChainFixture
 {
 public:
   CertificateCacheFixture()
     : certCache(10_s)
   {
-    identity = addIdentity("/TestCertificateCache/");
+    identity = m_keyChain.createIdentity("/TestCertificateCache");
     cert = identity.getDefaultKey().getDefaultCertificate();
   }
 
@@ -47,6 +48,7 @@
   Certificate cert;
 };
 
+BOOST_AUTO_TEST_SUITE(Security)
 BOOST_FIXTURE_TEST_SUITE(TestCertificateCache, CertificateCacheFixture)
 
 BOOST_AUTO_TEST_CASE(RemovalTime)
diff --git a/tests/unit/security/certificate-fetcher-direct-fetch.t.cpp b/tests/unit/security/certificate-fetcher-direct-fetch.t.cpp
index 25e0be5..7757f5b 100644
--- a/tests/unit/security/certificate-fetcher-direct-fetch.t.cpp
+++ b/tests/unit/security/certificate-fetcher-direct-fetch.t.cpp
@@ -20,9 +20,10 @@
  */
 
 #include "ndn-cxx/security/certificate-fetcher-direct-fetch.hpp"
-#include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
+
 #include "ndn-cxx/lp/nack.hpp"
 #include "ndn-cxx/lp/tags.hpp"
+#include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
 
 #include "tests/boost-test.hpp"
 #include "tests/unit/security/validator-fixture.hpp"
diff --git a/tests/unit/security/certificate-fetcher-from-network.t.cpp b/tests/unit/security/certificate-fetcher-from-network.t.cpp
index 8437c22..caf941a 100644
--- a/tests/unit/security/certificate-fetcher-from-network.t.cpp
+++ b/tests/unit/security/certificate-fetcher-from-network.t.cpp
@@ -20,8 +20,9 @@
  */
 
 #include "ndn-cxx/security/certificate-fetcher-from-network.hpp"
-#include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
+
 #include "ndn-cxx/lp/nack.hpp"
+#include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
 
 #include "tests/boost-test.hpp"
 #include "tests/unit/security/validator-fixture.hpp"
diff --git a/tests/unit/security/certificate.t.cpp b/tests/unit/security/certificate.t.cpp
index f645dbd..1069584 100644
--- a/tests/unit/security/certificate.t.cpp
+++ b/tests/unit/security/certificate.t.cpp
@@ -24,7 +24,7 @@
 #include "ndn-cxx/security/certificate.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/unit-test-time-fixture.hpp"
+#include "tests/unit/clock-fixture.hpp"
 
 #include <boost/lexical_cast.hpp>
 
@@ -36,7 +36,7 @@
 using namespace ndn::tests;
 
 BOOST_AUTO_TEST_SUITE(Security)
-BOOST_FIXTURE_TEST_SUITE(TestCertificate, UnitTestTimeFixture)
+BOOST_FIXTURE_TEST_SUITE(TestCertificate, ClockFixture)
 
 const uint8_t PUBLIC_KEY[] = {
   0x30, 0x81, 0x9d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
diff --git a/tests/unit/security/detail/certificate-bundle-decoder.t.cpp b/tests/unit/security/detail/certificate-bundle-decoder.t.cpp
index b6691ee..ae81c82 100644
--- a/tests/unit/security/detail/certificate-bundle-decoder.t.cpp
+++ b/tests/unit/security/detail/certificate-bundle-decoder.t.cpp
@@ -22,24 +22,24 @@
 #include "ndn-cxx/security/detail/certificate-bundle-decoder.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 namespace ndn {
 namespace security {
 namespace detail {
 namespace tests {
 
-class CertificateBundleDecoderFixture : public ndn::tests::IdentityManagementFixture
+class CertificateBundleDecoderFixture : public ndn::tests::KeyChainFixture
 {
 protected:
   CertificateBundleDecoderFixture()
   {
-    auto id1 = addIdentity("/hello/world1");
+    auto id1 = m_keyChain.createIdentity("/hello/world1");
     auto cert1 = id1.getDefaultKey().getDefaultCertificate();
     certBlock1 = cert1.wireEncode();
     m_certs.push_back(certBlock1);
 
-    auto id2 = addIdentity("/hello/world2");
+    auto id2 = m_keyChain.createIdentity("/hello/world2");
     auto cert2 = id2.getDefaultKey().getDefaultCertificate();
     certBlock2 = cert2.wireEncode();
     m_certs.push_back(certBlock2);
@@ -54,7 +54,7 @@
   CertificateBundleDecoder cbd;
   Block certBlock1;
   Block certBlock2;
-  int nCertsCompleted = 0;
+  size_t nCertsCompleted = 0;
 
 private:
   std::vector<Block> m_certs;
diff --git a/tests/unit/security/digest-sha256.t.cpp b/tests/unit/security/digest-sha256.t.cpp
index 674aaf5..83d2ca7 100644
--- a/tests/unit/security/digest-sha256.t.cpp
+++ b/tests/unit/security/digest-sha256.t.cpp
@@ -25,16 +25,14 @@
 #include "ndn-cxx/util/string-helper.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 namespace ndn {
 namespace security {
 namespace tests {
 
-using namespace ndn::tests;
-
 BOOST_AUTO_TEST_SUITE(Security)
-BOOST_FIXTURE_TEST_SUITE(TestDigestSha256, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_SUITE(TestDigestSha256, ndn::tests::KeyChainFixture)
 
 BOOST_AUTO_TEST_CASE(Sha256)
 {
diff --git a/tests/unit/security/interest-signer.t.cpp b/tests/unit/security/interest-signer.t.cpp
index 6d054ff..735668c 100644
--- a/tests/unit/security/interest-signer.t.cpp
+++ b/tests/unit/security/interest-signer.t.cpp
@@ -20,10 +20,10 @@
  */
 
 #include "ndn-cxx/security/interest-signer.hpp"
-#include "ndn-cxx/security/signing-helpers.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
+#include "tests/unit/clock-fixture.hpp"
 
 namespace ndn {
 namespace security {
@@ -31,12 +31,16 @@
 
 using namespace ndn::tests;
 
+class InterestSignerFixture : public ClockFixture, public KeyChainFixture
+{
+};
+
 BOOST_AUTO_TEST_SUITE(Security)
-BOOST_FIXTURE_TEST_SUITE(TestInterestSigner, IdentityManagementTimeFixture)
+BOOST_FIXTURE_TEST_SUITE(TestInterestSigner, InterestSignerFixture)
 
 BOOST_AUTO_TEST_CASE(V02)
 {
-  addIdentity("/test");
+  m_keyChain.createIdentity("/test");
 
   InterestSigner signer(m_keyChain);
   Interest i1 = signer.makeCommandInterest("/hello/world");
@@ -67,7 +71,7 @@
 
 BOOST_AUTO_TEST_CASE(V03)
 {
-  addIdentity("/test");
+  m_keyChain.createIdentity("/test");
 
   InterestSigner signer(m_keyChain);
   Interest i1("/hello/world");
diff --git a/tests/unit/security/key-chain.t.cpp b/tests/unit/security/key-chain.t.cpp
index b6dd0c6..a9e1eaf 100644
--- a/tests/unit/security/key-chain.t.cpp
+++ b/tests/unit/security/key-chain.t.cpp
@@ -20,12 +20,11 @@
  */
 
 #include "ndn-cxx/security/key-chain.hpp"
-#include "ndn-cxx/security/signing-helpers.hpp"
-#include "ndn-cxx/security/verification-helpers.hpp"
 #include "ndn-cxx/security/transform/private-key.hpp"
+#include "ndn-cxx/security/verification-helpers.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 #include "tests/unit/test-home-env-saver.hpp"
 
 namespace ndn {
@@ -209,7 +208,7 @@
   BOOST_CHECK_EQUAL(keyChain.getTpm().getTpmLocator(), "tpm-memory:");
 }
 
-BOOST_FIXTURE_TEST_CASE(SigningWithCorruptedPibTpm, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(SigningWithCorruptedPibTpm, KeyChainFixture)
 {
   Identity id = m_keyChain.createIdentity("/test");
 
@@ -223,7 +222,7 @@
   BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity(id)), KeyChain::InvalidSigningInfoError);
 }
 
-BOOST_FIXTURE_TEST_CASE(Management, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(Management, KeyChainFixture)
 {
   Name identityName("/test/id");
   Name identity2Name("/test/id2");
@@ -320,9 +319,9 @@
   BOOST_CHECK(m_keyChain.getPib().getIdentities().find(identityName) == m_keyChain.getPib().getIdentities().end());
 }
 
-BOOST_FIXTURE_TEST_CASE(GeneralSigningInterface, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(GeneralSigningInterface, KeyChainFixture)
 {
-  Identity id = addIdentity("/id");
+  Identity id = m_keyChain.createIdentity("/id");
   Key key = id.getDefaultKey();
   Certificate cert = key.getDefaultCertificate();
 
@@ -458,7 +457,7 @@
   }
 }
 
-BOOST_FIXTURE_TEST_CASE(PublicKeySigningDefaults, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(PublicKeySigningDefaults, KeyChainFixture)
 {
   Data data("/test/data");
 
@@ -466,7 +465,7 @@
   BOOST_CHECK_THROW(m_keyChain.sign(data, signingByIdentity("/non-existing/identity")), KeyChain::InvalidSigningInfoError);
 
   // Create identity with EC key and the corresponding self-signed certificate
-  Identity id = addIdentity("/ndn/test/ec", EcKeyParams());
+  Identity id = m_keyChain.createIdentity("/ndn/test/ec", EcKeyParams());
   BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id.getName())));
   BOOST_CHECK_EQUAL(data.getSignatureType(),
                     KeyChain::getSignatureType(EcKeyParams().getKeyType(), DigestAlgorithm::SHA256));
@@ -474,7 +473,7 @@
   BOOST_CHECK(id.getName().isPrefixOf(data.getKeyLocator()->getName()));
 
   // Create identity with RSA key and the corresponding self-signed certificate
-  id = addIdentity("/ndn/test/rsa", RsaKeyParams());
+  id = m_keyChain.createIdentity("/ndn/test/rsa", RsaKeyParams());
   BOOST_CHECK_NO_THROW(m_keyChain.sign(data, signingByIdentity(id.getName())));
   BOOST_CHECK_EQUAL(data.getSignatureType(),
                     KeyChain::getSignatureType(RsaKeyParams().getKeyType(), DigestAlgorithm::SHA256));
@@ -482,7 +481,7 @@
   BOOST_CHECK(id.getName().isPrefixOf(data.getKeyLocator()->getName()));
 }
 
-BOOST_FIXTURE_TEST_CASE(ImportPrivateKey, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(ImportPrivateKey, KeyChainFixture)
 {
   Name keyName("/test/device2");
   std::string rawKey("nPSNOHyZKsg2WLqHAs7MXGb0sjQb4zCT");
@@ -494,9 +493,9 @@
   BOOST_CHECK_THROW(m_keyChain.importPrivateKey(keyName, key), KeyChain::Error);
 }
 
-BOOST_FIXTURE_TEST_CASE(ExportImport, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(ExportImport, KeyChainFixture)
 {
-  Identity id = addIdentity("/TestKeyChain/ExportIdentity");
+  Identity id = m_keyChain.createIdentity("/TestKeyChain/ExportIdentity");
   Certificate cert = id.getDefaultKey().getDefaultCertificate();
 
   shared_ptr<SafeBag> exported = m_keyChain.exportSafeBag(cert, "1234", 4);
@@ -526,9 +525,9 @@
   BOOST_CHECK_EQUAL(m_keyChain.getTpm().hasKey(cert.getKeyName()), false);
 }
 
-BOOST_FIXTURE_TEST_CASE(SelfSignedCertValidity, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(SelfSignedCertValidity, KeyChainFixture)
 {
-  Certificate cert = addIdentity("/Security/TestKeyChain/SelfSignedCertValidity")
+  Certificate cert = m_keyChain.createIdentity("/Security/TestKeyChain/SelfSignedCertValidity")
                        .getDefaultKey()
                        .getDefaultCertificate();
   BOOST_CHECK(cert.isValid());
diff --git a/tests/unit/security/pib/impl/key-impl.t.cpp b/tests/unit/security/pib/impl/key-impl.t.cpp
index b2dfd96..be986a1 100644
--- a/tests/unit/security/pib/impl/key-impl.t.cpp
+++ b/tests/unit/security/pib/impl/key-impl.t.cpp
@@ -24,7 +24,7 @@
 #include "ndn-cxx/security/pib/pib.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 #include "tests/unit/security/pib/pib-data-fixture.hpp"
 
 namespace ndn {
@@ -131,7 +131,7 @@
 }
 
 class OverwriteFixture : public ndn::security::tests::PibDataFixture,
-                         public ndn::tests::IdentityManagementFixture
+                         public ndn::tests::KeyChainFixture
 {
 };
 
diff --git a/tests/unit/security/pib/pib-data-fixture.cpp b/tests/unit/security/pib/pib-data-fixture.cpp
index e88c48e..b641f31 100644
--- a/tests/unit/security/pib/pib-data-fixture.cpp
+++ b/tests/unit/security/pib/pib-data-fixture.cpp
@@ -21,11 +21,14 @@
 
 #include "tests/unit/security/pib/pib-data-fixture.hpp"
 
-// #include "ndn-cxx/security/pib/pib-memory.hpp"
+// #include "ndn-cxx/security/pib/impl/pib-memory.hpp"
+// #include "ndn-cxx/security/tpm/impl/back-end-mem.hpp"
 // #include "ndn-cxx/security/tpm/tpm.hpp"
-// #include "ndn-cxx/security/tpm/back-end-mem.hpp"
+// #include "ndn-cxx/util/string-helper.hpp"
 
-// #include <fstream>
+// #include "tests/boost-test.hpp"
+
+// #include <iostream>
 
 namespace ndn {
 namespace security {
@@ -50,7 +53,7 @@
 //         certName
 //           .append("issuer")
 //           .appendVersion(certVersion);
-//         v2::Certificate cert;
+//         Certificate cert;
 //         cert.setName(certName);
 //         cert.setFreshnessPeriod(1_h);
 //         cert.setContent(tpm.getPublicKey(keyName));
@@ -58,14 +61,13 @@
 //         // TODO: sign using KeyChain
 //         SignatureInfo info;
 //         info.setSignatureType(tlv::SignatureSha256WithEcdsa);
-//         info.setKeyLocator(KeyLocator(keyName));
+//         info.setKeyLocator(keyName);
 //         info.setValidityPeriod(ValidityPeriod(time::fromIsoString("20170102T000000"),
 //                                               time::fromIsoString("20180102T000000")));
 //         cert.setSignatureInfo(info);
 
 //         EncodingBuffer buf;
 //         cert.wireEncode(buf, true);
-
 //         cert.setSignatureValue(tpm.sign(buf.buf(), buf.size(), keyName, DigestAlgorithm::SHA256));
 
 //         printBytes(prefix + "_KEY" + to_string(keyId) + "_CERT" + to_string(certVersion),
@@ -83,7 +85,7 @@
 //   static void
 //   printBytes(const std::string& name, const Buffer& buffer)
 //   {
-//     printBytes(name, buffer.buf(), buffer.size());
+//     printBytes(name, buffer.data(), buffer.size());
 //   }
 
 //   static void
@@ -108,7 +110,7 @@
 //               << "};" << std::endl;
 //   }
 
-// public:
+// private:
 //   pib::PibMemory pib;
 //   Tpm tpm;
 // };
diff --git a/tests/unit/security/pib/pib-data-fixture.hpp b/tests/unit/security/pib/pib-data-fixture.hpp
index 66e65eb..0009d0f 100644
--- a/tests/unit/security/pib/pib-data-fixture.hpp
+++ b/tests/unit/security/pib/pib-data-fixture.hpp
@@ -19,8 +19,8 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_UNIT_SECURITY_PIB_DATA_FIXTURE_HPP
-#define NDN_TESTS_UNIT_SECURITY_PIB_DATA_FIXTURE_HPP
+#ifndef NDN_CXX_TESTS_UNIT_SECURITY_PIB_PIB_DATA_FIXTURE_HPP
+#define NDN_CXX_TESTS_UNIT_SECURITY_PIB_PIB_DATA_FIXTURE_HPP
 
 #include "ndn-cxx/security/certificate.hpp"
 
@@ -61,4 +61,4 @@
 } // namespace security
 } // namespace ndn
 
-#endif // NDN_TESTS_UNIT_SECURITY_PIB_DATA_FIXTURE_HPP
+#endif // NDN_CXX_TESTS_UNIT_SECURITY_PIB_PIB_DATA_FIXTURE_HPP
diff --git a/tests/unit/security/pib/pib-impl.t.cpp b/tests/unit/security/pib/pib-impl.t.cpp
index e16f658..971d995 100644
--- a/tests/unit/security/pib/pib-impl.t.cpp
+++ b/tests/unit/security/pib/pib-impl.t.cpp
@@ -52,20 +52,16 @@
 class PibSqlite3Fixture : public PibDataFixture
 {
 public:
-  PibSqlite3Fixture()
-    : tmpPath(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "DbTest")
-    , pib(tmpPath.c_str())
-  {
-  }
-
   ~PibSqlite3Fixture()
   {
-    boost::filesystem::remove_all(tmpPath);
+    boost::filesystem::remove_all(m_path);
   }
 
+private:
+  const boost::filesystem::path m_path{boost::filesystem::path(UNIT_TESTS_TMPDIR) / "TestPibImpl"};
+
 public:
-  boost::filesystem::path tmpPath;
-  PibSqlite3 pib;
+  PibSqlite3 pib{m_path.string()};
 };
 
 using PibImpls = boost::mpl::vector<PibMemoryFixture, PibSqlite3Fixture>;
diff --git a/tests/unit/security/signature-sha256-with-ecdsa.t.cpp b/tests/unit/security/signature-sha256-with-ecdsa.t.cpp
index 3881756..de5edb9 100644
--- a/tests/unit/security/signature-sha256-with-ecdsa.t.cpp
+++ b/tests/unit/security/signature-sha256-with-ecdsa.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,9 +23,8 @@
 #include "ndn-cxx/security/verification-helpers.hpp"
 #include "ndn-cxx/util/scheduler.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/test-common.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 
 namespace ndn {
 namespace security {
@@ -33,11 +32,11 @@
 
 using namespace ndn::tests;
 
-class SignatureSha256EcdsaTimeFixture : public IdentityManagementTimeFixture
+class SignatureSha256EcdsaTimeFixture : public IoKeyChainFixture
 {
 public:
   SignatureSha256EcdsaTimeFixture()
-    : scheduler(io)
+    : scheduler(m_io)
   {
   }
 
@@ -108,7 +107,7 @@
 
 BOOST_AUTO_TEST_CASE(DataSignature)
 {
-  Identity identity = addIdentity("/SecurityTestSignatureSha256WithEcdsa/DataSignature", EcKeyParams());
+  Identity identity = m_keyChain.createIdentity("/SecurityTestSignatureSha256WithEcdsa/DataSignature", EcKeyParams());
 
   Data testData("/SecurityTestSignatureSha256WithEcdsa/DataSignature/Data1");
   char content[5] = "1234";
@@ -123,7 +122,7 @@
 
 BOOST_AUTO_TEST_CASE(InterestSignature)
 {
-  Identity identity = addIdentity("/SecurityTestSignatureSha256WithEcdsa/InterestSignature", EcKeyParams());
+  Identity identity = m_keyChain.createIdentity("/SecurityTestSignatureSha256WithEcdsa/InterestSignature", EcKeyParams());
 
   auto interest = makeInterest("/SecurityTestSignatureSha256WithEcdsa/InterestSignature/Interest1");
   auto interest11 = makeInterest("/SecurityTestSignatureSha256WithEcdsa/InterestSignature/Interest1");
diff --git a/tests/unit/security/signature-sha256-with-rsa.t.cpp b/tests/unit/security/signature-sha256-with-rsa.t.cpp
index 2363551..d52d923 100644
--- a/tests/unit/security/signature-sha256-with-rsa.t.cpp
+++ b/tests/unit/security/signature-sha256-with-rsa.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,9 +23,8 @@
 #include "ndn-cxx/security/verification-helpers.hpp"
 #include "ndn-cxx/util/scheduler.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/test-common.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 
 namespace ndn {
 namespace security {
@@ -33,11 +32,11 @@
 
 using namespace ndn::tests;
 
-class SignatureSha256RsaTimeFixture : public IdentityManagementTimeFixture
+class SignatureSha256RsaTimeFixture : public IoKeyChainFixture
 {
 public:
   SignatureSha256RsaTimeFixture()
-    : scheduler(io)
+    : scheduler(m_io)
   {
   }
 
@@ -113,7 +112,7 @@
 
 BOOST_AUTO_TEST_CASE(DataSignature)
 {
-  Identity identity = addIdentity("/SecurityTestSignatureSha256WithRsa/DataSignature", RsaKeyParams());
+  Identity identity = m_keyChain.createIdentity("/SecurityTestSignatureSha256WithRsa/DataSignature", RsaKeyParams());
 
   Data testData("/SecurityTestSignatureSha256WithRsa/DataSignature/Data1");
   char content[5] = "1234";
@@ -128,7 +127,7 @@
 
 BOOST_AUTO_TEST_CASE(InterestSignature)
 {
-  Identity identity = addIdentity("/SecurityTestSignatureSha256WithRsa/InterestSignature", RsaKeyParams());
+  Identity identity = m_keyChain.createIdentity("/SecurityTestSignatureSha256WithRsa/InterestSignature", RsaKeyParams());
 
   auto interest = makeInterest("/SecurityTestSignatureSha256WithRsa/InterestSignature/Interest1");
   auto interest11 = makeInterest("/SecurityTestSignatureSha256WithRsa/InterestSignature/Interest1");
diff --git a/tests/unit/security/signing-helpers.t.cpp b/tests/unit/security/signing-helpers.t.cpp
index f4493fe..a515c16 100644
--- a/tests/unit/security/signing-helpers.t.cpp
+++ b/tests/unit/security/signing-helpers.t.cpp
@@ -30,8 +30,6 @@
 BOOST_AUTO_TEST_SUITE(Security)
 BOOST_AUTO_TEST_SUITE(TestSigningHelpers)
 
-// update of this test case deferred until the new IdentityManagementFixture is available
-
 BOOST_AUTO_TEST_CASE(Identity)
 {
   Name identity("/identity");
diff --git a/tests/unit/security/tpm/back-end-wrapper-file.hpp b/tests/unit/security/tpm/back-end-wrapper-file.hpp
index 16b9bf2..2689e07 100644
--- a/tests/unit/security/tpm/back-end-wrapper-file.hpp
+++ b/tests/unit/security/tpm/back-end-wrapper-file.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -38,7 +38,7 @@
 {
 public:
   BackEndWrapperFile()
-    : m_tmpPath(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "TpmFileTest")
+    : m_tmpPath(boost::filesystem::path(UNIT_TESTS_TMPDIR) / "TpmBackEndFile")
     , m_impl(make_unique<BackEndFile>(m_tmpPath.string()))
   {
   }
diff --git a/tests/unit/security/trust-anchor-container.t.cpp b/tests/unit/security/trust-anchor-container.t.cpp
index b25805f..18da58a 100644
--- a/tests/unit/security/trust-anchor-container.t.cpp
+++ b/tests/unit/security/trust-anchor-container.t.cpp
@@ -23,7 +23,8 @@
 #include "ndn-cxx/util/io.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
+#include "tests/unit/clock-fixture.hpp"
 
 #include <boost/filesystem.hpp>
 
@@ -34,47 +35,37 @@
 
 using namespace ndn::tests;
 
-BOOST_AUTO_TEST_SUITE(Security)
-
 /**
  * This fixture creates a directory and prepares two certificates.
  * cert1 is written to a file under the directory, while cert2 is not.
  */
-class AnchorContainerTestFixture : public IdentityManagementTimeFixture
+class TrustAnchorContainerFixture : public ClockFixture, public KeyChainFixture
 {
 public:
-  AnchorContainerTestFixture()
+  TrustAnchorContainerFixture()
   {
-    namespace fs = boost::filesystem;
+    boost::filesystem::create_directories(certDirPath);
 
-    fs::create_directory(fs::path(UNIT_TEST_CONFIG_PATH));
-
-    certDirPath = fs::path(UNIT_TEST_CONFIG_PATH) / "test-cert-dir";
-    fs::create_directory(certDirPath);
-
-    certPath1 = fs::path(UNIT_TEST_CONFIG_PATH) / "test-cert-dir" / "trust-anchor-1.cert";
-    certPath2 = fs::path(UNIT_TEST_CONFIG_PATH) / "test-cert-dir" / "trust-anchor-2.cert";
-
-    identity1 = addIdentity("/TestAnchorContainer/First");
+    identity1 = m_keyChain.createIdentity("/TestAnchorContainer/First");
     cert1 = identity1.getDefaultKey().getDefaultCertificate();
-    saveCertToFile(cert1, certPath1.string());
+    saveCert(cert1, certPath1.string());
 
-    identity2 = addIdentity("/TestAnchorContainer/Second");
+    identity2 = m_keyChain.createIdentity("/TestAnchorContainer/Second");
     cert2 = identity2.getDefaultKey().getDefaultCertificate();
-    saveCertToFile(cert2, certPath2.string());
+    saveCert(cert2, certPath2.string());
   }
 
-  ~AnchorContainerTestFixture()
+  ~TrustAnchorContainerFixture() override
   {
-    boost::filesystem::remove_all(UNIT_TEST_CONFIG_PATH);
+    boost::filesystem::remove_all(certDirPath);
   }
 
 public:
-  TrustAnchorContainer anchorContainer;
+  const boost::filesystem::path certDirPath{boost::filesystem::path(UNIT_TESTS_TMPDIR) / "test-cert-dir"};
+  const boost::filesystem::path certPath1{certDirPath / "trust-anchor-1.cert"};
+  const boost::filesystem::path certPath2{certDirPath / "trust-anchor-2.cert"};
 
-  boost::filesystem::path certDirPath;
-  boost::filesystem::path certPath1;
-  boost::filesystem::path certPath2;
+  TrustAnchorContainer anchorContainer;
 
   Identity identity1;
   Identity identity2;
@@ -83,7 +74,8 @@
   Certificate cert2;
 };
 
-BOOST_FIXTURE_TEST_SUITE(TestTrustAnchorContainer, AnchorContainerTestFixture)
+BOOST_AUTO_TEST_SUITE(Security)
+BOOST_FIXTURE_TEST_SUITE(TestTrustAnchorContainer, TrustAnchorContainerFixture)
 
 // one static group and one dynamic group created from file
 BOOST_AUTO_TEST_CASE(Insert)
@@ -138,7 +130,7 @@
   BOOST_CHECK(anchorContainer.find(identity2.getName()) == nullptr);
   BOOST_CHECK_EQUAL(anchorContainer.getGroup("group").size(), 1);
 
-  saveCertToFile(cert2, certPath2.string());
+  saveCert(cert2, certPath2.string());
 
   advanceClocks(100_ms, 11);
 
@@ -155,7 +147,7 @@
   BOOST_CHECK_EQUAL(anchorContainer.getGroup("group").size(), 0);
 }
 
-BOOST_FIXTURE_TEST_CASE(FindByInterest, AnchorContainerTestFixture)
+BOOST_AUTO_TEST_CASE(FindByInterest)
 {
   anchorContainer.insert("group1", certPath1.string(), 1_s);
   Interest interest(identity1.getName());
@@ -165,9 +157,9 @@
   Interest interest2(Name(identity1.getName()).appendVersion());
   BOOST_CHECK(anchorContainer.find(interest2) == nullptr);
 
-  Certificate cert3 = addCertificate(identity1.getDefaultKey(), "3");
-  Certificate cert4 = addCertificate(identity1.getDefaultKey(), "4");
-  Certificate cert5 = addCertificate(identity1.getDefaultKey(), "5");
+  auto cert3 = makeCert(identity1.getDefaultKey(), "3");
+  auto cert4 = makeCert(identity1.getDefaultKey(), "4");
+  auto cert5 = makeCert(identity1.getDefaultKey(), "5");
 
   Certificate cert3Copy = cert3;
   anchorContainer.insert("group2", std::move(cert3Copy));
diff --git a/tests/unit/security/validation-policy-accept-all.t.cpp b/tests/unit/security/validation-policy-accept-all.t.cpp
index 6a9f0f1..cd94cf7 100644
--- a/tests/unit/security/validation-policy-accept-all.t.cpp
+++ b/tests/unit/security/validation-policy-accept-all.t.cpp
@@ -40,7 +40,7 @@
 public:
   ValidationPolicyAcceptAllFixture()
   {
-    identity = addIdentity("/Security/TestValidationPolicyAcceptAll");
+    identity = m_keyChain.createIdentity("/Security/TestValidationPolicyAcceptAll");
     // don't add trust anchors
   }
 
diff --git a/tests/unit/security/validation-policy-command-interest.t.cpp b/tests/unit/security/validation-policy-command-interest.t.cpp
index 9f32056..9b8f360 100644
--- a/tests/unit/security/validation-policy-command-interest.t.cpp
+++ b/tests/unit/security/validation-policy-command-interest.t.cpp
@@ -20,13 +20,12 @@
  */
 
 #include "ndn-cxx/security/validation-policy-command-interest.hpp"
+
 #include "ndn-cxx/security/command-interest-signer.hpp"
-#include "ndn-cxx/security/signing-helpers.hpp"
 #include "ndn-cxx/security/validation-policy-accept-all.hpp"
 #include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 #include "tests/unit/security/validator-fixture.hpp"
 
 #include <boost/lexical_cast.hpp>
@@ -239,7 +238,7 @@
   advanceClocks(1_s);
   auto i3 = makeCommandInterest(identity); // signed at +2s
 
-  systemClock->advance(-18_s); // verifying at -16s
+  m_systemClock->advance(-18_s); // verifying at -16s
   VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
   rewindClockAfterValidation();
 
@@ -277,11 +276,11 @@
   advanceClocks(300_ms);
   auto i4 = makeCommandInterest(identity); // signed at +1400ms
 
-  systemClock->advance(-300_ms); // verifying at +1100ms
+  m_systemClock->advance(-300_ms); // verifying at +1100ms
   VALIDATE_SUCCESS(i1, "Should succeed");
   rewindClockAfterValidation();
 
-  systemClock->advance(-1100_ms); // verifying at 0ms
+  m_systemClock->advance(-1100_ms); // verifying at 0ms
   VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
   rewindClockAfterValidation();
 
@@ -400,7 +399,7 @@
 BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicyCommandInterestFixture<UnlimitedRecordsOptions>)
 {
   std::vector<Identity> identities;
-  for (int i = 0; i < 20; ++i) {
+  for (size_t i = 0; i < 20; ++i) {
     Identity id = this->addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
     this->cache.insert(id.getDefaultKey().getDefaultCertificate());
     identities.push_back(id);
@@ -408,7 +407,7 @@
 
   auto i1 = makeCommandInterest(identities.at(0)); // signed at 0s
   advanceClocks(1_s);
-  for (int i = 0; i < 20; ++i) {
+  for (size_t i = 0; i < 20; ++i) {
     auto i2 = makeCommandInterest(identities.at(i)); // signed at +1s
 
     VALIDATE_SUCCESS(i2, "Should succeed");
@@ -462,7 +461,7 @@
   advanceClocks(120_s);
   auto i3 = makeCommandInterest(identity); // signed at +360s
 
-  systemClock->advance(-360_s); // rewind system clock to 0s
+  m_systemClock->advance(-360_s); // rewind system clock to 0s
   VALIDATE_SUCCESS(i1, "Should succeed");
   rewindClockAfterValidation();
 
diff --git a/tests/unit/security/validation-policy-config.t.cpp b/tests/unit/security/validation-policy-config.t.cpp
index e660598..38c5986 100644
--- a/tests/unit/security/validation-policy-config.t.cpp
+++ b/tests/unit/security/validation-policy-config.t.cpp
@@ -20,10 +20,10 @@
  */
 
 #include "ndn-cxx/security/validation-policy-config.hpp"
+
 #include "ndn-cxx/security/transform/base64-encode.hpp"
 #include "ndn-cxx/security/transform/buffer-source.hpp"
 #include "ndn-cxx/security/transform/stream-sink.hpp"
-#include "ndn-cxx/util/logger.hpp"
 #include "ndn-cxx/util/io.hpp"
 
 #include "tests/boost-test.hpp"
@@ -91,7 +91,7 @@
 {
 public:
   ValidationPolicyConfigFixture()
-    : path(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "security" / "v2" / "validation-policy-config")
+    : path(boost::filesystem::path(UNIT_TESTS_TMPDIR) / "security" / "validation-policy-config")
   {
     boost::filesystem::create_directories(path);
     baseConfig = R"CONF(
@@ -116,8 +116,7 @@
 
   ~ValidationPolicyConfigFixture()
   {
-    boost::system::error_code ec;
-    boost::filesystem::remove_all(path, ec);
+    boost::filesystem::remove_all(path);
   }
 
 protected:
@@ -135,7 +134,7 @@
   {
     BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
 
-    this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+    this->saveIdentityCert(this->identity, (this->path / "identity.ndncert").string());
     this->policy.load(this->baseConfig + R"CONF(
         trust-anchor
         {
@@ -167,7 +166,7 @@
         )CONF";
     }
 
-    this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+    this->saveIdentityCert(this->identity, (this->path / "identity.ndncert").string());
 
     BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
 
@@ -192,7 +191,7 @@
         }
       )CONF");
 
-    this->saveCertificate(this->identity, (this->path / "identity.ndncert").string());
+    this->saveIdentityCert(this->identity, (this->path / "identity.ndncert").string());
 
     BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
 
@@ -298,7 +297,7 @@
     BOOST_CHECK_EQUAL(this->policy.m_isConfigured, false);
 
     boost::filesystem::create_directories(this->path / "keys");
-    this->saveCertificate(this->identity, (this->path / "keys" / "identity.ndncert").string());
+    this->saveIdentityCert(this->identity, (this->path / "keys" / "identity.ndncert").string());
 
     this->policy.load(this->baseConfig + R"CONF(
         trust-anchor
diff --git a/tests/unit/security/validation-policy-signed-interest.t.cpp b/tests/unit/security/validation-policy-signed-interest.t.cpp
index f46e5ad..d9cddb5 100644
--- a/tests/unit/security/validation-policy-signed-interest.t.cpp
+++ b/tests/unit/security/validation-policy-signed-interest.t.cpp
@@ -20,13 +20,12 @@
  */
 
 #include "ndn-cxx/security/validation-policy-signed-interest.hpp"
+
 #include "ndn-cxx/security/interest-signer.hpp"
-#include "ndn-cxx/security/signing-helpers.hpp"
 #include "ndn-cxx/security/validation-policy-accept-all.hpp"
 #include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 #include "tests/unit/security/validator-fixture.hpp"
 
 #include <boost/lexical_cast.hpp>
@@ -188,7 +187,7 @@
 BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicySignedInterestFixture<UnlimitedRecordsOptions>)
 {
   std::vector<Identity> identities;
-  for (int i = 0; i < 20; ++i) {
+  for (size_t i = 0; i < 20; ++i) {
     Identity id = addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
     cache.insert(id.getDefaultKey().getDefaultCertificate());
     identities.push_back(id);
@@ -196,7 +195,7 @@
 
   auto i1 = makeSignedInterest(identities.at(0)); // signed at 0s
   advanceClocks(1_s);
-  for (int i = 0; i < 20; ++i) {
+  for (size_t i = 0; i < 20; ++i) {
     auto i2 = makeSignedInterest(identities.at(i)); // signed at +1s
 
     VALIDATE_SUCCESS(i2, "Should succeed");
@@ -295,7 +294,7 @@
   advanceClocks(1_s);
   auto i3 = makeSignedInterest(identity); // signed at +2s
 
-  systemClock->advance(-18_s); // verifying at -16s
+  m_systemClock->advance(-18_s); // verifying at -16s
   VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
   rewindClockAfterValidation();
 
@@ -334,11 +333,11 @@
   advanceClocks(300_ms);
   auto i4 = makeSignedInterest(identity); // signed at +1400ms
 
-  systemClock->advance(-300_ms); // verifying at +1100ms
+  m_systemClock->advance(-300_ms); // verifying at +1100ms
   VALIDATE_SUCCESS(i1, "Should succeed");
   rewindClockAfterValidation();
 
-  systemClock->advance(-1100_ms); // verifying at 0ms
+  m_systemClock->advance(-1100_ms); // verifying at 0ms
   VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
   rewindClockAfterValidation();
 
diff --git a/tests/unit/security/validation-policy.t.cpp b/tests/unit/security/validation-policy.t.cpp
index 41cde4d..e982f72 100644
--- a/tests/unit/security/validation-policy.t.cpp
+++ b/tests/unit/security/validation-policy.t.cpp
@@ -22,21 +22,19 @@
 #include "ndn-cxx/security/validation-policy.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 namespace ndn {
 namespace security {
 inline namespace v2 {
 namespace tests {
 
-using namespace ndn::tests;
-
 BOOST_AUTO_TEST_SUITE(Security)
-BOOST_FIXTURE_TEST_SUITE(TestValidationPolicy, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_SUITE(TestValidationPolicy, ndn::tests::KeyChainFixture)
 
 BOOST_AUTO_TEST_CASE(ExtractIdentityNameFromKeyLocator)
 {
-  auto id = addIdentity("/random/identity");
+  auto id = m_keyChain.createIdentity("/random/identity");
 
   auto keyName = id.getDefaultKey().getName();
   auto certName = id.getDefaultKey().getDefaultCertificate().getName();
diff --git a/tests/unit/security/validator-config.t.cpp b/tests/unit/security/validator-config.t.cpp
index dac6913..0f4f694 100644
--- a/tests/unit/security/validator-config.t.cpp
+++ b/tests/unit/security/validator-config.t.cpp
@@ -20,12 +20,13 @@
  */
 
 #include "ndn-cxx/security/validator-config.hpp"
+
 #include "ndn-cxx/security/certificate-fetcher-offline.hpp"
 #include "ndn-cxx/security/command-interest-signer.hpp"
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 #include "tests/unit/security/validator-config/common.hpp"
 
 namespace ndn {
@@ -35,7 +36,7 @@
 using namespace ndn::tests;
 
 BOOST_AUTO_TEST_SUITE(Security)
-BOOST_FIXTURE_TEST_SUITE(TestValidatorConfig, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_SUITE(TestValidatorConfig, KeyChainFixture)
 
 // This test only for API, actual tests are in ValidationPolicyConfig and corresponding CertificateFetchers
 
@@ -46,16 +47,16 @@
   ValidatorConfig v1(face);
   BOOST_CHECK_EQUAL(v1.m_policyConfig.m_isConfigured, false);
 
-  ValidatorConfig v2(make_unique<v2::CertificateFetcherOffline>());
+  ValidatorConfig v2(make_unique<CertificateFetcherOffline>());
   BOOST_CHECK_EQUAL(v2.m_policyConfig.m_isConfigured, false);
 }
 
-class ValidatorConfigFixture : public IdentityManagementFixture
+class ValidatorConfigFixture : public KeyChainFixture
 {
 public:
   ValidatorConfigFixture()
-    : path(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "security" / "validator-config")
-    , validator(make_unique<v2::CertificateFetcherOffline>())
+    : path(boost::filesystem::path(UNIT_TESTS_TMPDIR) / "security" / "validator-config")
+    , validator(make_unique<CertificateFetcherOffline>())
   {
     boost::filesystem::create_directories(path);
     config = R"CONF(
@@ -117,11 +118,11 @@
 
 BOOST_AUTO_TEST_CASE(FromSection)
 {
-  validator.load(v2::validator_config::tests::makeSection(config), "config-file-from-section");
+  validator.load(validator_config::tests::makeSection(config), "config-file-from-section");
   BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
 
   // should reload policy
-  validator.load(v2::validator_config::tests::makeSection(config), "config-file-from-section");
+  validator.load(validator_config::tests::makeSection(config), "config-file-from-section");
   BOOST_CHECK_EQUAL(validator.m_policyConfig.m_isConfigured, true);
 }
 
diff --git a/tests/unit/security/validator-config/checker.t.cpp b/tests/unit/security/validator-config/checker.t.cpp
index 55e48a1..029996c 100644
--- a/tests/unit/security/validator-config/checker.t.cpp
+++ b/tests/unit/security/validator-config/checker.t.cpp
@@ -39,7 +39,7 @@
 BOOST_AUTO_TEST_SUITE(Security)
 BOOST_AUTO_TEST_SUITE(ValidatorConfig)
 
-class CheckerFixture : public IdentityManagementFixture
+class CheckerFixture : public KeyChainFixture
 {
 public:
   CheckerFixture()
diff --git a/tests/unit/security/validator-config/common.hpp b/tests/unit/security/validator-config/common.hpp
index de72e3f..c4a4fe3 100644
--- a/tests/unit/security/validator-config/common.hpp
+++ b/tests/unit/security/validator-config/common.hpp
@@ -19,8 +19,8 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
-#define NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
+#ifndef NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_CONFIG_COMMON_HPP
+#define NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_CONFIG_COMMON_HPP
 
 #include "ndn-cxx/security/validator-config/common.hpp"
 
@@ -47,4 +47,4 @@
 } // namespace security
 } // namespace ndn
 
-#endif // NDN_TESTS_SECURITY_V2_VALIDATOR_CONFIG_COMMON_HPP
+#endif // NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_CONFIG_COMMON_HPP
diff --git a/tests/unit/security/validator-config/filter.t.cpp b/tests/unit/security/validator-config/filter.t.cpp
index 9f6029e..5b77a12 100644
--- a/tests/unit/security/validator-config/filter.t.cpp
+++ b/tests/unit/security/validator-config/filter.t.cpp
@@ -22,7 +22,6 @@
 #include "ndn-cxx/security/validator-config/filter.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
 #include "tests/unit/security/validator-config/common.hpp"
 #include "tests/unit/security/validator-fixture.hpp"
 
@@ -38,33 +37,35 @@
 BOOST_AUTO_TEST_SUITE(Security)
 BOOST_AUTO_TEST_SUITE(ValidatorConfig)
 
-BOOST_FIXTURE_TEST_SUITE(TestFilter, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_SUITE(TestFilter, KeyChainFixture)
 
 #define CHECK_FOR_MATCHES(filter, same, longer, shorter, different) \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV02Pkt::makeName("/foo/bar", m_keyChain), \
-                                 InterestV02Pkt::makeState()), same);    \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV03Pkt::makeName("/foo/bar", m_keyChain), \
-                                 InterestV03Pkt::makeState()), same);    \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Data, DataPkt::makeName("/foo/bar", m_keyChain), \
-                                 DataPkt::makeState()), same);           \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV02Pkt::makeName("/foo/bar/bar", m_keyChain), \
-                                 InterestV02Pkt::makeState()), longer);  \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV03Pkt::makeName("/foo/bar/bar", m_keyChain), \
-                                 InterestV03Pkt::makeState()), longer);  \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Data, DataPkt::makeName("/foo/bar/bar", m_keyChain), \
-                                 DataPkt::makeState()), longer);         \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV02Pkt::makeName("/foo", m_keyChain), \
-                                 InterestV02Pkt::makeState()), shorter); \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV03Pkt::makeName("/foo", m_keyChain), \
-                                 InterestV03Pkt::makeState()), shorter); \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Data, DataPkt::makeName("/foo", m_keyChain), \
-                                 DataPkt::makeState()), shorter);        \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV02Pkt::makeName("/other/prefix", m_keyChain), \
-                                 InterestV02Pkt::makeState()), different); \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV03Pkt::makeName("/other/prefix", m_keyChain), \
-                                 InterestV03Pkt::makeState()), different); \
-  BOOST_CHECK_EQUAL(filter.match(tlv::Data, DataPkt::makeName("/other/prefix", m_keyChain), \
-                                 DataPkt::makeState()), different);
+  do { \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV02Pkt::makeName("/foo/bar", m_keyChain), \
+                                   InterestV02Pkt::makeState()), same);    \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV03Pkt::makeName("/foo/bar", m_keyChain), \
+                                   InterestV03Pkt::makeState()), same);    \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Data, DataPkt::makeName("/foo/bar", m_keyChain), \
+                                   DataPkt::makeState()), same);           \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV02Pkt::makeName("/foo/bar/bar", m_keyChain), \
+                                   InterestV02Pkt::makeState()), longer);  \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV03Pkt::makeName("/foo/bar/bar", m_keyChain), \
+                                   InterestV03Pkt::makeState()), longer);  \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Data, DataPkt::makeName("/foo/bar/bar", m_keyChain), \
+                                   DataPkt::makeState()), longer);         \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV02Pkt::makeName("/foo", m_keyChain), \
+                                   InterestV02Pkt::makeState()), shorter); \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV03Pkt::makeName("/foo", m_keyChain), \
+                                   InterestV03Pkt::makeState()), shorter); \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Data, DataPkt::makeName("/foo", m_keyChain), \
+                                   DataPkt::makeState()), shorter);        \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV02Pkt::makeName("/other/prefix", m_keyChain), \
+                                   InterestV02Pkt::makeState()), different); \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Interest, InterestV03Pkt::makeName("/other/prefix", m_keyChain), \
+                                   InterestV03Pkt::makeState()), different); \
+    BOOST_CHECK_EQUAL(filter.match(tlv::Data, DataPkt::makeName("/other/prefix", m_keyChain), \
+                                   DataPkt::makeState()), different); \
+  } while (false)
 
 BOOST_AUTO_TEST_CASE(RelationName)
 {
@@ -90,7 +91,7 @@
   CHECK_FOR_MATCHES(f3, false, true, false, false);
 }
 
-BOOST_FIXTURE_TEST_SUITE(Create, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_SUITE(Create, KeyChainFixture)
 
 BOOST_AUTO_TEST_CASE(Errors)
 {
diff --git a/tests/unit/security/validator-config/rule.t.cpp b/tests/unit/security/validator-config/rule.t.cpp
index 75eb6dc..04c6e8d 100644
--- a/tests/unit/security/validator-config/rule.t.cpp
+++ b/tests/unit/security/validator-config/rule.t.cpp
@@ -40,7 +40,7 @@
 BOOST_AUTO_TEST_SUITE(ValidatorConfig)
 
 template<class Packet>
-class RuleFixture : public IdentityManagementFixture
+class RuleFixture : public KeyChainFixture
 {
 public:
   RuleFixture()
diff --git a/tests/unit/security/validator-fixture.cpp b/tests/unit/security/validator-fixture.cpp
new file mode 100644
index 0000000..8bb4713
--- /dev/null
+++ b/tests/unit/security/validator-fixture.cpp
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2020 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 "tests/unit/security/validator-fixture.hpp"
+
+#include "ndn-cxx/security/additional-description.hpp"
+
+namespace ndn {
+namespace security {
+inline namespace v2 {
+namespace tests {
+
+const time::milliseconds ValidatorFixtureBase::s_mockPeriod{250};
+const int ValidatorFixtureBase::s_mockTimes = 200;
+
+ValidatorFixtureBase::ValidatorFixtureBase()
+{
+  processInterest = [this] (const Interest& interest) {
+    auto cert = cache.find(interest);
+    if (cert != nullptr) {
+      face.receive(*cert);
+    }
+  };
+}
+
+void
+ValidatorFixtureBase::mockNetworkOperations()
+{
+  util::signal::ScopedConnection conn = face.onSendInterest.connect([this] (const Interest& interest) {
+    if (processInterest) {
+      m_io.post(bind(processInterest, interest));
+    }
+  });
+  advanceClocks(s_mockPeriod, s_mockTimes);
+}
+
+Identity
+ValidatorFixtureBase::addSubCertificate(const Name& subIdentityName, const Identity& issuer)
+{
+  auto subId = m_keyChain.createIdentity(subIdentityName);
+  auto cert = subId.getDefaultKey().getDefaultCertificate();
+  cert.setName(cert.getKeyName()
+               .append("parent")
+               .appendVersion());
+
+  SignatureInfo info;
+  auto now = time::system_clock::now();
+  info.setValidityPeriod(ValidityPeriod(now, now + 90_days));
+
+  AdditionalDescription description;
+  description.set("type", "sub-certificate");
+  info.addCustomTlv(description.wireEncode());
+
+  m_keyChain.sign(cert, signingByIdentity(issuer).setSignatureInfo(info));
+  m_keyChain.setDefaultCertificate(subId.getDefaultKey(), cert);
+
+  return subId;
+}
+
+Name
+InterestV02Pkt::makeName(Name name, KeyChain& keyChain)
+{
+  Interest interest(name);
+  interest.setCanBePrefix(false);
+  SigningInfo params;
+  params.setSignedInterestFormat(SignedInterestFormat::V02);
+  keyChain.sign(interest, params);
+  return interest.getName();
+}
+
+Name
+InterestV03Pkt::makeName(Name name, KeyChain& keyChain)
+{
+  Interest interest(name);
+  interest.setCanBePrefix(false);
+  SigningInfo params;
+  params.setSignedInterestFormat(SignedInterestFormat::V03);
+  keyChain.sign(interest, params);
+  return interest.getName();
+}
+
+} // namespace tests
+} // inline namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/tests/unit/security/validator-fixture.hpp b/tests/unit/security/validator-fixture.hpp
index e9e5d5b..8da34f0 100644
--- a/tests/unit/security/validator-fixture.hpp
+++ b/tests/unit/security/validator-fixture.hpp
@@ -19,15 +19,15 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
-#define NDN_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
+#ifndef NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
+#define NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
 
 #include "ndn-cxx/security/validator.hpp"
 #include "ndn-cxx/security/certificate-fetcher-from-network.hpp"
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 
 #include <boost/lexical_cast.hpp>
 
@@ -36,27 +36,54 @@
 inline namespace v2 {
 namespace tests {
 
-template<class ValidationPolicy, class CertificateFetcher = CertificateFetcherFromNetwork>
-class ValidatorFixture : public ndn::tests::IdentityManagementTimeFixture
+class ValidatorFixtureBase : public ndn::tests::IoKeyChainFixture
 {
-public:
-  ValidatorFixture()
-    : face(io, {true, true})
-    , validator(make_unique<ValidationPolicy>(), make_unique<CertificateFetcher>(face))
-    , policy(static_cast<ValidationPolicy&>(validator.getPolicy()))
-    , cache(100_days)
-    , lastError(ValidationError::Code::NO_ERROR)
+protected:
+  ValidatorFixtureBase();
+
+  void
+  mockNetworkOperations();
+
+  /** \brief undo clock advancement of mockNetworkOperations()
+   */
+  void
+  rewindClockAfterValidation()
   {
-    processInterest = [this] (const Interest& interest) {
-      auto cert = cache.find(interest);
-      if (cert != nullptr) {
-        face.receive(*cert);
-      }
-    };
+    m_systemClock->advance(s_mockPeriod * s_mockTimes * -1);
   }
 
-  virtual
-  ~ValidatorFixture() = default;
+  /**
+   * @brief Issues a certificate for @p subIdentityName signed by @p issuer
+   *
+   * If the identity does not exist, it is created.
+   * A new key is generated as the default key for the identity.
+   * A default certificate for the key is signed by the issuer using its default certificate.
+   *
+   * @return The sub-identity
+   */
+  Identity
+  addSubCertificate(const Name& subIdentityName, const Identity& issuer);
+
+protected:
+  util::DummyClientFace face{m_io, {true, true}};
+  std::function<void(const Interest&)> processInterest;
+  CertificateCache cache{100_days};
+  ValidationError lastError{ValidationError::Code::NO_ERROR};
+
+private:
+  const static time::milliseconds s_mockPeriod;
+  const static int s_mockTimes;
+};
+
+template<class ValidationPolicyT, class CertificateFetcherT = CertificateFetcherFromNetwork>
+class ValidatorFixture : public ValidatorFixtureBase
+{
+protected:
+  ValidatorFixture()
+    : validator(make_unique<ValidationPolicyT>(), make_unique<CertificateFetcherT>(face))
+    , policy(static_cast<ValidationPolicyT&>(validator.getPolicy()))
+  {
+  }
 
   template<class Packet>
   void
@@ -82,55 +109,21 @@
     BOOST_CHECK_EQUAL(nCallbacks, 1);
   }
 
-  void
-  mockNetworkOperations()
-  {
-    util::signal::ScopedConnection connection = face.onSendInterest.connect([this] (const Interest& interest) {
-        if (processInterest != nullptr) {
-          io.post(bind(processInterest, interest));
-        }
-      });
-    advanceClocks(time::milliseconds(s_mockPeriod), s_mockTimes);
-  }
-
-  /** \brief undo clock advancement of mockNetworkOperations
-   */
-  void
-  rewindClockAfterValidation()
-  {
-    this->systemClock->advance(time::milliseconds(s_mockPeriod * s_mockTimes * -1));
-  }
-
-public:
-  util::DummyClientFace face;
-  std::function<void(const Interest& interest)> processInterest;
+protected:
   Validator validator;
-  ValidationPolicy& policy;
-
-  CertificateCache cache;
-  ValidationError lastError;
-
-private:
-  const static int s_mockPeriod;
-  const static int s_mockTimes;
+  ValidationPolicyT& policy;
 };
 
-template<class ValidationPolicy, class CertificateFetcher>
-const int ValidatorFixture<ValidationPolicy, CertificateFetcher>::s_mockPeriod = 250;
-
-template<class ValidationPolicy, class CertificateFetcher>
-const int ValidatorFixture<ValidationPolicy, CertificateFetcher>::s_mockTimes = 200;
-
-template<class ValidationPolicy, class CertificateFetcher = CertificateFetcherFromNetwork>
-class HierarchicalValidatorFixture : public ValidatorFixture<ValidationPolicy, CertificateFetcher>
+template<class ValidationPolicyT, class CertificateFetcherT = CertificateFetcherFromNetwork>
+class HierarchicalValidatorFixture : public ValidatorFixture<ValidationPolicyT, CertificateFetcherT>
 {
-public:
+protected:
   HierarchicalValidatorFixture()
   {
-    identity = this->addIdentity("/Security/ValidatorFixture");
+    identity = this->m_keyChain.createIdentity("/Security/ValidatorFixture");
     subIdentity = this->addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
-    subSelfSignedIdentity = this->addIdentity("/Security/ValidatorFixture/Sub1/Sub2");
-    otherIdentity = this->addIdentity("/Security/OtherIdentity");
+    subSelfSignedIdentity = this->m_keyChain.createIdentity("/Security/ValidatorFixture/Sub1/Sub2");
+    otherIdentity = this->m_keyChain.createIdentity("/Security/OtherIdentity");
 
     this->validator.loadAnchor("", Certificate(identity.getDefaultKey().getDefaultCertificate()));
 
@@ -140,34 +133,33 @@
     this->cache.insert(otherIdentity.getDefaultKey().getDefaultCertificate());
   }
 
-public:
+protected:
   Identity identity;
   Identity subIdentity;
   Identity subSelfSignedIdentity;
   Identity otherIdentity;
 };
 
-#define VALIDATE_SUCCESS(packet, message) this->template validate(packet, message, true, __LINE__)
-#define VALIDATE_FAILURE(packet, message) this->template validate(packet, message, false, __LINE__)
+#define VALIDATE_SUCCESS(packet, message) this->validate(packet, message, true, __LINE__)
+#define VALIDATE_FAILURE(packet, message) this->validate(packet, message, false, __LINE__)
 
 class DummyValidationState : public ValidationState
 {
 public:
-  ~DummyValidationState()
+  ~DummyValidationState() override
   {
     m_outcome = false;
   }
 
   void
-  fail(const ValidationError& error) override
+  fail(const ValidationError&) override
   {
-    // BOOST_TEST_MESSAGE(error);
     m_outcome = false;
   }
 
 private:
   void
-  verifyOriginalPacket(const Certificate& trustedCert) override
+  verifyOriginalPacket(const Certificate&) override
   {
     // do nothing
   }
@@ -179,17 +171,16 @@
   }
 };
 
-
 struct DataPkt
 {
-  static uint32_t
+  static constexpr uint32_t
   getType()
   {
     return tlv::Data;
   }
 
   static Name
-  makeName(Name name, KeyChain& keyChain)
+  makeName(Name name, KeyChain&)
   {
     return name;
   }
@@ -203,22 +194,14 @@
 
 struct InterestV02Pkt
 {
-  static uint32_t
+  static constexpr uint32_t
   getType()
   {
     return tlv::Interest;
   }
 
   static Name
-  makeName(Name name, KeyChain& keyChain)
-  {
-    Interest interest(name);
-    interest.setCanBePrefix(false);
-    SigningInfo params;
-    params.setSignedInterestFormat(SignedInterestFormat::V02);
-    keyChain.sign(interest, params);
-    return interest.getName();
-  }
+  makeName(Name name, KeyChain& keyChain);
 
   static shared_ptr<ValidationState>
   makeState()
@@ -231,22 +214,14 @@
 
 struct InterestV03Pkt
 {
-  static uint32_t
+  static constexpr uint32_t
   getType()
   {
     return tlv::Interest;
   }
 
   static Name
-  makeName(Name name, KeyChain& keyChain)
-  {
-    Interest interest(name);
-    interest.setCanBePrefix(false);
-    SigningInfo params;
-    params.setSignedInterestFormat(SignedInterestFormat::V03);
-    keyChain.sign(interest, params);
-    return interest.getName();
-  }
+  makeName(Name name, KeyChain& keyChain);
 
   static shared_ptr<ValidationState>
   makeState()
@@ -262,4 +237,4 @@
 } // namespace security
 } // namespace ndn
 
-#endif // NDN_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
+#endif // NDN_CXX_TESTS_UNIT_SECURITY_VALIDATOR_FIXTURE_HPP
diff --git a/tests/unit/security/validator-null.t.cpp b/tests/unit/security/validator-null.t.cpp
index 103f8f7..9d04cb8 100644
--- a/tests/unit/security/validator-null.t.cpp
+++ b/tests/unit/security/validator-null.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,21 +22,18 @@
 #include "ndn-cxx/security/validator-null.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 namespace ndn {
 namespace security {
 namespace tests {
 
-using namespace ndn::tests;
-
 BOOST_AUTO_TEST_SUITE(Security)
-BOOST_FIXTURE_TEST_SUITE(TestValidatorNull, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_SUITE(TestValidatorNull, ndn::tests::KeyChainFixture)
 
 BOOST_AUTO_TEST_CASE(ValidateData)
 {
-  auto identity = addIdentity("/TestValidator/Null");
+  auto identity = m_keyChain.createIdentity("/TestValidator/Null");
   Data data("/Some/Other/Data/Name");
   m_keyChain.sign(data, signingByIdentity(identity));
 
@@ -48,7 +45,7 @@
 
 BOOST_AUTO_TEST_CASE(ValidateInterest)
 {
-  auto identity = addIdentity("/TestValidator/Null");
+  auto identity = m_keyChain.createIdentity("/TestValidator/Null");
   Interest interest("/Some/Other/Interest/Name");
   m_keyChain.sign(interest, signingByIdentity(identity));
 
diff --git a/tests/unit/security/validator.t.cpp b/tests/unit/security/validator.t.cpp
index faecf56..adf72d3 100644
--- a/tests/unit/security/validator.t.cpp
+++ b/tests/unit/security/validator.t.cpp
@@ -198,7 +198,7 @@
 {
 public:
   void
-  checkPolicy(const Data& data, const shared_ptr<ValidationState>& state,
+  checkPolicy(const Data&, const shared_ptr<ValidationState>& state,
               const ValidationContinuation& continueValidation) override
   {
     continueValidation(nullptr, state);
@@ -264,28 +264,8 @@
     // create another key for the same identity and sign it properly
     Key parentKey = m_keyChain.createKey(subIdentity);
     Key requestedKey = subIdentity.getKey(interest.getName());
-
-    Name certificateName = requestedKey.getName();
-    certificateName
-    .append("looper")
-    .appendVersion();
-    v2::Certificate certificate;
-    certificate.setName(certificateName);
-
-    // set metainfo
-    certificate.setContentType(tlv::ContentType_Key);
-    certificate.setFreshnessPeriod(1_h);
-
-    // set content
-    certificate.setContent(requestedKey.getPublicKey().data(), requestedKey.getPublicKey().size());
-
-    // set signature-info
-    SignatureInfo info;
-    info.setValidityPeriod(security::ValidityPeriod(time::system_clock::now() - 10_days,
-                                                    time::system_clock::now() + 10_days));
-
-    m_keyChain.sign(certificate, signingByKey(parentKey).setSignatureInfo(info));
-    face.receive(certificate);
+    auto cert = makeCert(requestedKey, "looper", parentKey);
+    face.receive(cert);
   };
 
   Data data("/Security/ValidatorFixture/Sub1/Sub2/Data");
@@ -307,13 +287,13 @@
 
 BOOST_AUTO_TEST_CASE(LoopedCertChain)
 {
-  auto s1 = addIdentity("/loop");
+  auto s1 = m_keyChain.createIdentity("/loop");
   auto k1 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key1")));
   auto k2 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key2")));
   auto k3 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key3")));
 
   auto makeCert = [this] (Key& key, const Key& signer) {
-    v2::Certificate request = key.getDefaultCertificate();
+    Certificate request = key.getDefaultCertificate();
     request.setName(Name(key.getName()).append("looper").appendVersion());
 
     SignatureInfo info;
diff --git a/tests/unit/security/validity-period.t.cpp b/tests/unit/security/validity-period.t.cpp
index 768e774..1dc7740 100644
--- a/tests/unit/security/validity-period.t.cpp
+++ b/tests/unit/security/validity-period.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,7 +22,7 @@
 #include "ndn-cxx/security/validity-period.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/unit-test-time-fixture.hpp"
+#include "tests/unit/clock-fixture.hpp"
 
 #include <boost/lexical_cast.hpp>
 
@@ -35,14 +35,12 @@
 BOOST_AUTO_TEST_SUITE(Security)
 BOOST_AUTO_TEST_SUITE(TestValidityPeriod)
 
-BOOST_FIXTURE_TEST_CASE(ConstructorSetter, UnitTestTimeFixture)
+BOOST_FIXTURE_TEST_CASE(ConstructorSetter, ClockFixture)
 {
-  time::system_clock::TimePoint now = this->systemClock->getNow();
-
-  time::system_clock::TimePoint notBefore = now - 1_day;
-  time::system_clock::TimePoint notAfter = notBefore + 2_days;
-
-  ValidityPeriod validity1 = ValidityPeriod(notBefore, notAfter);
+  auto now = m_systemClock->getNow();
+  auto notBefore = now - 1_day;
+  auto notAfter = notBefore + 2_days;
+  ValidityPeriod validity1(notBefore, notAfter);
 
   auto period = validity1.getPeriod();
   BOOST_CHECK_GE(period.first, notBefore); // fractional seconds will be removed
diff --git a/tests/unit/security/verification-helpers.t.cpp b/tests/unit/security/verification-helpers.t.cpp
index f1e7185..476bbe3 100644
--- a/tests/unit/security/verification-helpers.t.cpp
+++ b/tests/unit/security/verification-helpers.t.cpp
@@ -23,9 +23,8 @@
 #include "ndn-cxx/security/transform/public-key.hpp"
 // #include "ndn-cxx/util/string-helper.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/key-chain-fixture.hpp"
+#include "tests/test-common.hpp"
 
 #include <boost/mpl/vector.hpp>
 
@@ -39,12 +38,12 @@
 BOOST_AUTO_TEST_SUITE(TestVerificationHelpers)
 
 // // Use this test case to regenerate the dataset if the signature format changes
-// BOOST_FIXTURE_TEST_CASE(Generator, IdentityManagementFixture)
+// BOOST_FIXTURE_TEST_CASE(Generator, KeyChainFixture)
 // {
-//   Identity wrongIdentity = addIdentity("/Security/TestVerificationHelpers/Wrong");
+//   Identity wrongIdentity = m_keyChain.createIdentity("/Security/TestVerificationHelpers/Wrong");
 //   std::map<std::string, SigningInfo> identities = {
-//     {"Ecdsa", signingByIdentity(addIdentity("/Security/TestVerificationHelpers/EC", EcKeyParams()))},
-//     {"Rsa", signingByIdentity(addIdentity("/Security/TestVerificationHelpers/RSA", RsaKeyParams()))},
+//     {"Ecdsa", signingByIdentity(m_keyChain.createIdentity("/Security/TestVerificationHelpers/EC", EcKeyParams()))},
+//     {"Rsa", signingByIdentity(m_keyChain.createIdentity("/Security/TestVerificationHelpers/RSA", RsaKeyParams()))},
 //     {"Sha256", signingWithSha256()}
 //   };
 
@@ -601,7 +600,7 @@
   // - pib::Key version is tested as part of key-chain.t.cpp (Security/TestKeyChain)
 }
 
-BOOST_FIXTURE_TEST_CASE(VerifyHmac, IdentityManagementFixture)
+BOOST_FIXTURE_TEST_CASE(VerifyHmac, KeyChainFixture)
 {
   const Tpm& tpm = m_keyChain.getTpm();
   Data data("/data");
diff --git a/tests/unit/transport/tcp-transport.t.cpp b/tests/unit/transport/tcp-transport.t.cpp
index 991bf1c..cb577cc 100644
--- a/tests/unit/transport/tcp-transport.t.cpp
+++ b/tests/unit/transport/tcp-transport.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,13 +22,12 @@
 #include "ndn-cxx/transport/tcp-transport.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/transport/transport-fixture.hpp"
 
 namespace ndn {
 namespace tests {
 
 BOOST_AUTO_TEST_SUITE(Transport)
-BOOST_FIXTURE_TEST_SUITE(TestTcpTransport, TransportFixture)
+BOOST_AUTO_TEST_SUITE(TestTcpTransport)
 
 using ndn::Transport;
 
diff --git a/tests/unit/transport/unix-transport.t.cpp b/tests/unit/transport/unix-transport.t.cpp
index 5711859..a8946f4 100644
--- a/tests/unit/transport/unix-transport.t.cpp
+++ b/tests/unit/transport/unix-transport.t.cpp
@@ -22,13 +22,12 @@
 #include "ndn-cxx/transport/unix-transport.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/transport/transport-fixture.hpp"
 
 namespace ndn {
 namespace tests {
 
 BOOST_AUTO_TEST_SUITE(Transport)
-BOOST_FIXTURE_TEST_SUITE(TestUnixTransport, TransportFixture)
+BOOST_AUTO_TEST_SUITE(TestUnixTransport)
 
 using ndn::Transport;
 
diff --git a/tests/unit/unit-test-time-fixture.hpp b/tests/unit/unit-test-time-fixture.hpp
deleted file mode 100644
index fcbaa77..0000000
--- a/tests/unit/unit-test-time-fixture.hpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 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.
- */
-
-#ifndef NDN_TESTS_UNIT_UNIT_TEST_TIME_FIXTURE_HPP
-#define NDN_TESTS_UNIT_UNIT_TEST_TIME_FIXTURE_HPP
-
-#include "ndn-cxx/util/time-unit-test-clock.hpp"
-
-#include <boost/asio/io_service.hpp>
-
-namespace ndn {
-namespace tests {
-
-/** \brief a test fixture that overrides steady clock and system clock
- */
-class UnitTestTimeFixture
-{
-public:
-  UnitTestTimeFixture()
-    : steadyClock(make_shared<time::UnitTestSteadyClock>())
-    , systemClock(make_shared<time::UnitTestSystemClock>())
-  {
-    time::setCustomClocks(steadyClock, systemClock);
-  }
-
-  ~UnitTestTimeFixture()
-  {
-    time::setCustomClocks(nullptr, nullptr);
-  }
-
-  /** \brief advance steady and system clocks
-   *
-   *  Clocks are advanced in increments of \p tick for \p nTicks ticks.
-   *  After each tick, io_service is polled to process pending I/O events.
-   *
-   *  Exceptions thrown during I/O events are propagated to the caller.
-   *  Clock advancing would stop in case of an exception.
-   */
-  void
-  advanceClocks(const time::nanoseconds& tick, size_t nTicks = 1)
-  {
-    this->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.
-   *  After each tick, io_service is polled to process pending I/O events.
-   *
-   *  Exceptions thrown during I/O events are propagated to the caller.
-   *  Clock advancing would stop in case of an exception.
-   */
-  void
-  advanceClocks(const time::nanoseconds& tick, const time::nanoseconds& total)
-  {
-    BOOST_ASSERT(tick > time::nanoseconds::zero());
-    BOOST_ASSERT(total >= time::nanoseconds::zero());
-
-    time::nanoseconds remaining = total;
-    while (remaining > time::nanoseconds::zero()) {
-      if (remaining >= tick) {
-        steadyClock->advance(tick);
-        systemClock->advance(tick);
-        remaining -= tick;
-      }
-      else {
-        steadyClock->advance(remaining);
-        systemClock->advance(remaining);
-        remaining = time::nanoseconds::zero();
-      }
-
-      if (io.stopped())
-        io.reset();
-      io.poll();
-    }
-  }
-
-public:
-  shared_ptr<time::UnitTestSteadyClock> steadyClock;
-  shared_ptr<time::UnitTestSystemClock> systemClock;
-  boost::asio::io_service io;
-};
-
-} // namespace tests
-} // namespace ndn
-
-#endif // NDN_TESTS_UNIT_UNIT_TEST_TIME_FIXTURE_HPP
diff --git a/tests/unit/unit-tests-pch.hpp b/tests/unit/unit-tests-pch.hpp
index 5f2ed67..dd67e02 100644
--- a/tests/unit/unit-tests-pch.hpp
+++ b/tests/unit/unit-tests-pch.hpp
@@ -19,8 +19,8 @@
  * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
  */
 
-#ifndef NDN_TESTS_UNIT_UNIT_TESTS_PCH_HPP
-#define NDN_TESTS_UNIT_UNIT_TESTS_PCH_HPP
+#ifndef NDN_CXX_TESTS_UNIT_UNIT_TESTS_PCH_HPP
+#define NDN_CXX_TESTS_UNIT_UNIT_TESTS_PCH_HPP
 
 #include "tests/tests-pch.hpp"
 
@@ -30,6 +30,6 @@
 #include "ndn-cxx/security/validator.hpp"
 #include "ndn-cxx/util/config-file.hpp"
 
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 
-#endif // NDN_TESTS_UNIT_UNIT_TESTS_PCH_HPP
+#endif // NDN_CXX_TESTS_UNIT_UNIT_TESTS_PCH_HPP
diff --git a/tests/unit/util/dummy-client-face.t.cpp b/tests/unit/util/dummy-client-face.t.cpp
index acd6297..b823be2 100644
--- a/tests/unit/util/dummy-client-face.t.cpp
+++ b/tests/unit/util/dummy-client-face.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -21,9 +21,8 @@
 
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/test-common.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 
 namespace ndn {
 namespace util {
@@ -32,7 +31,7 @@
 using namespace ndn::tests;
 
 BOOST_AUTO_TEST_SUITE(Util)
-BOOST_FIXTURE_TEST_SUITE(TestDummyClientFace, ndn::tests::IdentityManagementTimeFixture)
+BOOST_FIXTURE_TEST_SUITE(TestDummyClientFace, IoKeyChainFixture)
 
 BOOST_AUTO_TEST_CASE(ProcessEventsOverride)
 {
@@ -42,15 +41,15 @@
     BOOST_CHECK_EQUAL(timeout, 200_ms);
   };
 
-  DummyClientFace face(io, {false, false, override});
+  DummyClientFace face(m_io, {false, false, override});
   face.processEvents(200_ms);
   BOOST_CHECK(isOverrideInvoked);
 }
 
 BOOST_AUTO_TEST_CASE(BroadcastLink)
 {
-  DummyClientFace face1(io, m_keyChain, DummyClientFace::Options{true, true});
-  DummyClientFace face2(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face1(m_io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face2(m_io, m_keyChain, DummyClientFace::Options{true, true});
   face1.linkTo(face2);
 
   int nFace1Interest = 0;
@@ -97,14 +96,14 @@
 
 BOOST_AUTO_TEST_CASE(BroadcastLinkDestroy)
 {
-  DummyClientFace face1(io, m_keyChain, DummyClientFace::Options{true, true});
-  DummyClientFace face2(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face1(m_io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face2(m_io, m_keyChain, DummyClientFace::Options{true, true});
 
   face1.linkTo(face2);
   face2.unlink();
   BOOST_CHECK(face1.m_bcastLink == nullptr);
 
-  DummyClientFace face3(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face3(m_io, m_keyChain, DummyClientFace::Options{true, true});
   face1.linkTo(face2);
   face3.linkTo(face1);
   face2.unlink();
@@ -113,10 +112,10 @@
 
 BOOST_AUTO_TEST_CASE(AlreadyLinkException)
 {
-  DummyClientFace face1(io, m_keyChain, DummyClientFace::Options{true, true});
-  DummyClientFace face2(io, m_keyChain, DummyClientFace::Options{true, true});
-  DummyClientFace face3(io, m_keyChain, DummyClientFace::Options{true, true});
-  DummyClientFace face4(io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face1(m_io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face2(m_io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face3(m_io, m_keyChain, DummyClientFace::Options{true, true});
+  DummyClientFace face4(m_io, m_keyChain, DummyClientFace::Options{true, true});
 
   face1.linkTo(face2);
   face3.linkTo(face4);
diff --git a/tests/unit/util/io.t.cpp b/tests/unit/util/io.t.cpp
index 9340279..1ebaf61 100644
--- a/tests/unit/util/io.t.cpp
+++ b/tests/unit/util/io.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,7 +22,7 @@
 #include "ndn-cxx/util/io.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/identity-management-fixture.hpp"
+#include "tests/key-chain-fixture.hpp"
 
 #include <boost/filesystem.hpp>
 #include <boost/mpl/vector.hpp>
@@ -100,7 +100,7 @@
 {
 protected:
   FileIoFixture()
-    : filepath(boost::filesystem::path(UNIT_TEST_CONFIG_PATH) / "TestIo")
+    : filepath(boost::filesystem::path(UNIT_TESTS_TMPDIR) / "TestIo")
     , filename(filepath.string())
   {
     boost::filesystem::create_directories(filepath.parent_path());
@@ -327,23 +327,23 @@
 BOOST_AUTO_TEST_SUITE_END() // FileIo
 
 class IdCertFixture : public FileIoFixture
-                    , public IdentityManagementFixture
+                    , public KeyChainFixture
 {
 };
 
 BOOST_FIXTURE_TEST_CASE(IdCert, IdCertFixture)
 {
-  auto identity = addIdentity("/TestIo/IdCert", RsaKeyParams());
+  auto identity = m_keyChain.createIdentity("/TestIo/IdCert", RsaKeyParams());
   const auto& cert = identity.getDefaultKey().getDefaultCertificate();
   io::save(cert, filename);
 
-  auto readCert = io::load<security::v2::Certificate>(filename);
+  auto readCert = io::load<security::Certificate>(filename);
 
   BOOST_REQUIRE(readCert != nullptr);
   BOOST_CHECK_EQUAL(cert.getName(), readCert->getName());
 
   this->writeFile<std::string>("");
-  readCert = io::load<security::v2::Certificate>(filename);
+  readCert = io::load<security::Certificate>(filename);
   BOOST_REQUIRE(readCert == nullptr);
 }
 
diff --git a/tests/unit/util/logging.t.cpp b/tests/unit/util/logging.t.cpp
index 8bbc638..24ae88b 100644
--- a/tests/unit/util/logging.t.cpp
+++ b/tests/unit/util/logging.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,7 +23,7 @@
 #include "ndn-cxx/util/logger.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/unit-test-time-fixture.hpp"
+#include "tests/unit/clock-fixture.hpp"
 
 #if BOOST_VERSION >= 105900
 #include <boost/test/tools/output_test_stream.hpp>
@@ -169,14 +169,14 @@
 const time::microseconds LOG_SYSTIME(1468108800311239LL);
 const std::string LOG_SYSTIME_STR("1468108800.311239");
 
-class LoggingFixture : public ndn::tests::UnitTestTimeFixture
+class LoggingFixture : public ndn::tests::ClockFixture
 {
 protected:
   LoggingFixture()
     : m_oldEnabledLevel(Logging::get().getLevels())
     , m_oldDestination(Logging::get().getDestination())
   {
-    this->systemClock->setNow(LOG_SYSTIME);
+    m_systemClock->setNow(LOG_SYSTIME);
     Logging::get().resetLevels();
     Logging::setDestination(os);
   }
diff --git a/tests/unit/util/notification-stream.t.cpp b/tests/unit/util/notification-stream.t.cpp
index ada10c5..2df3014 100644
--- a/tests/unit/util/notification-stream.t.cpp
+++ b/tests/unit/util/notification-stream.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018 Regents of the University of California,
+ * Copyright (c) 2014-2020 Regents of the University of California,
  *                         Arizona Board of Regents,
  *                         Colorado State University,
  *                         University Pierre & Marie Curie, Sorbonne University,
@@ -29,7 +29,7 @@
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 #include "tests/unit/util/simple-notification.hpp"
 
 namespace ndn {
@@ -37,13 +37,14 @@
 namespace tests {
 
 BOOST_AUTO_TEST_SUITE(Util)
-BOOST_FIXTURE_TEST_SUITE(TestNotificationStream, ndn::tests::IdentityManagementTimeFixture)
+BOOST_FIXTURE_TEST_SUITE(TestNotificationStream, ndn::tests::IoKeyChainFixture)
 
 BOOST_AUTO_TEST_CASE(Post)
 {
-  DummyClientFace face(io, m_keyChain);
-  util::NotificationStream<SimpleNotification> notificationStream(face,
-    "/localhost/nfd/NotificationStreamTest", m_keyChain);
+  DummyClientFace face(m_io, m_keyChain);
+  NotificationStream<SimpleNotification> notificationStream(face,
+                                                            "/localhost/nfd/NotificationStreamTest",
+                                                            m_keyChain);
 
   SimpleNotification event1("msg1");
   notificationStream.postNotification(event1);
diff --git a/tests/unit/util/notification-subscriber.t.cpp b/tests/unit/util/notification-subscriber.t.cpp
index e3b7aa9..d8f9dfd 100644
--- a/tests/unit/util/notification-subscriber.t.cpp
+++ b/tests/unit/util/notification-subscriber.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2019 Regents of the University of California,
+ * Copyright (c) 2014-2020 Regents of the University of California,
  *                         Arizona Board of Regents,
  *                         Colorado State University,
  *                         University Pierre & Marie Curie, Sorbonne University,
@@ -28,9 +28,8 @@
 #include "ndn-cxx/util/notification-subscriber.hpp"
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/test-common.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 #include "tests/unit/util/simple-notification.hpp"
 
 namespace ndn {
@@ -39,12 +38,12 @@
 
 using namespace ndn::tests;
 
-class NotificationSubscriberFixture : public IdentityManagementTimeFixture
+class NotificationSubscriberFixture : public IoKeyChainFixture
 {
 public:
   NotificationSubscriberFixture()
-    : streamPrefix("ndn:/NotificationSubscriberTest")
-    , subscriberFace(io, m_keyChain)
+    : streamPrefix("/NotificationSubscriberTest")
+    , subscriberFace(m_io, m_keyChain)
     , subscriber(subscriberFace, streamPrefix, 1_s)
     , nextSendNotificationNo(0)
   {
diff --git a/tests/unit/util/scheduler.t.cpp b/tests/unit/util/scheduler.t.cpp
index 021c1f0..1bd3860 100644
--- a/tests/unit/util/scheduler.t.cpp
+++ b/tests/unit/util/scheduler.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -22,7 +22,7 @@
 #include "ndn-cxx/util/scheduler.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/unit-test-time-fixture.hpp"
+#include "tests/unit/io-fixture.hpp"
 
 #include <boost/lexical_cast.hpp>
 
@@ -30,16 +30,10 @@
 namespace scheduler {
 namespace tests {
 
-class SchedulerFixture : public ndn::tests::UnitTestTimeFixture
+class SchedulerFixture : public ndn::tests::IoFixture
 {
-public:
-  SchedulerFixture()
-    : scheduler(io)
-  {
-  }
-
-public:
-  Scheduler scheduler;
+protected:
+  Scheduler scheduler{m_io};
 };
 
 BOOST_AUTO_TEST_SUITE(Util)
@@ -201,9 +195,8 @@
 
 BOOST_AUTO_TEST_CASE(CancelAllWithScopedEventId) // Bug 3691
 {
-  Scheduler sched(io);
-  ScopedEventId eid = sched.schedule(10_ms, []{});
-  sched.cancelAllEvents();
+  ScopedEventId eid = scheduler.schedule(10_ms, []{});
+  scheduler.cancelAllEvents();
   eid.cancel(); // should not crash
 
   // avoid "test case [...] did not check any assertions" message from Boost.Test
diff --git a/tests/unit/util/segment-fetcher.t.cpp b/tests/unit/util/segment-fetcher.t.cpp
index 7f63db8..c58c1f9 100644
--- a/tests/unit/util/segment-fetcher.t.cpp
+++ b/tests/unit/util/segment-fetcher.t.cpp
@@ -25,10 +25,9 @@
 #include "ndn-cxx/lp/nack.hpp"
 #include "ndn-cxx/util/dummy-client-face.hpp"
 
-#include "tests/boost-test.hpp"
-#include "tests/make-interest-data.hpp"
+#include "tests/test-common.hpp"
 #include "tests/unit/dummy-validator.hpp"
-#include "tests/unit/identity-management-time-fixture.hpp"
+#include "tests/unit/io-key-chain-fixture.hpp"
 
 #include <set>
 
@@ -38,27 +37,20 @@
 
 using namespace ndn::tests;
 
-class Fixture : public IdentityManagementTimeFixture
+class SegmentFetcherFixture : public IoKeyChainFixture
 {
 public:
-  Fixture()
-    : face(io, m_keyChain)
-  {
-  }
-
   static shared_ptr<Data>
   makeDataSegment(const Name& baseName, uint64_t segment, bool isFinal)
   {
     const uint8_t buffer[] = "Hello, world!";
-
-    auto data = make_shared<Data>(Name(baseName).appendSegment(segment));
-    data->setFreshnessPeriod(1_s);
+    auto data = makeData(Name(baseName).appendSegment(segment));
     data->setContent(buffer, sizeof(buffer));
+    data->setFreshnessPeriod(1_s);
     if (isFinal) {
       data->setFinalBlock(data->getName()[-1]);
     }
-
-    return signData(data);
+    return data;
   }
 
   void
@@ -90,21 +82,20 @@
   }
 
   void
-  nackLastInterest(lp::NackReason nackReason)
+  nackLastInterest(lp::NackReason reason)
   {
     const Interest& lastInterest = face.sentInterests.back();
-    lp::Nack nack = makeNack(lastInterest, nackReason);
-    face.receive(nack);
+    face.receive(makeNack(lastInterest, reason));
     advanceClocks(10_ms);
   }
 
   void
   connectSignals(const shared_ptr<SegmentFetcher>& fetcher)
   {
-    fetcher->onInOrderData.connect(bind(&Fixture::onInOrderData, this, _1));
-    fetcher->onInOrderComplete.connect(bind(&Fixture::onInOrderComplete, this));
-    fetcher->onComplete.connect(bind(&Fixture::onComplete, this, _1));
-    fetcher->onError.connect(bind(&Fixture::onError, this, _1));
+    fetcher->onInOrderData.connect(bind(&SegmentFetcherFixture::onInOrderData, this, _1));
+    fetcher->onInOrderComplete.connect(bind(&SegmentFetcherFixture::onInOrderComplete, this));
+    fetcher->onComplete.connect(bind(&SegmentFetcherFixture::onComplete, this, _1));
+    fetcher->onError.connect(bind(&SegmentFetcherFixture::onError, this, _1));
 
     fetcher->afterSegmentReceived.connect([this] (const auto&) { ++this->nAfterSegmentReceived; });
     fetcher->afterSegmentValidated.connect([this] (const auto &) { ++this->nAfterSegmentValidated; });
@@ -133,7 +124,7 @@
 
       uniqSegmentsSent.insert(interest.getName().get(-1).toSegment());
       if (uniqSegmentsSent.size() == nSegments) {
-        io.stop();
+        m_io.stop();
       }
     }
     else {
@@ -154,7 +145,7 @@
   }
 
 public:
-  DummyClientFace face;
+  DummyClientFace face{m_io, m_keyChain};
   std::set<uint64_t> uniqSegmentsSent;
 
   int nErrors = 0;
@@ -178,7 +169,7 @@
 };
 
 BOOST_AUTO_TEST_SUITE(Util)
-BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, Fixture)
+BOOST_FIXTURE_TEST_SUITE(TestSegmentFetcher, SegmentFetcherFixture)
 
 BOOST_AUTO_TEST_CASE(InvalidOptions)
 {
@@ -318,7 +309,7 @@
 
   shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
                                                              acceptValidator);
-  face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+  face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
   connectSignals(fetcher);
 
   face.processEvents(1_s);
@@ -341,7 +332,7 @@
   sendNackInsteadOfDropping = false;
 
   auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
-  face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+  face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
   connectSignals(fetcher);
 
   face.processEvents(1_s);
@@ -366,7 +357,7 @@
 
   shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
                                                              acceptValidator);
-  face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+  face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
   connectSignals(fetcher);
 
   face.processEvents(1_s);
@@ -390,7 +381,7 @@
   defaultSegmentToSend = 47;
 
   auto fetcher = SegmentFetcher::start(face, Interest("/hello/world"), acceptValidator, options);
-  face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+  face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
   connectSignals(fetcher);
 
   face.processEvents(1_s);
@@ -635,7 +626,7 @@
 
   shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
                                                              acceptValidator);
-  face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+  face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
   connectSignals(fetcher);
 
   face.processEvents(1_s);
@@ -660,7 +651,7 @@
 
   shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
                                                              acceptValidator);
-  face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+  face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
   connectSignals(fetcher);
 
   face.processEvents(1_s);
@@ -680,7 +671,7 @@
   segmentsToDropOrNack.push(0);
   sendNackInsteadOfDropping = true;
   nackReason = lp::NackReason::NO_ROUTE;
-  face.onSendInterest.connect(bind(&Fixture::onInterest, this, _1));
+  face.onSendInterest.connect(bind(&SegmentFetcherFixture::onInterest, this, _1));
 
   shared_ptr<SegmentFetcher> fetcher = SegmentFetcher::start(face, Interest("/hello/world"),
                                                              acceptValidator);
diff --git a/tests/unit/util/sqlite3-statement.t.cpp b/tests/unit/util/sqlite3-statement.t.cpp
index c5ee8b6..a78b077 100644
--- a/tests/unit/util/sqlite3-statement.t.cpp
+++ b/tests/unit/util/sqlite3-statement.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -31,13 +31,13 @@
 namespace util {
 namespace tests {
 
-class Sqlite3StatementTestFixture
+class Sqlite3DbFixture
 {
 public:
-  Sqlite3StatementTestFixture()
-    : m_path(boost::filesystem::path(UNIT_TEST_CONFIG_PATH))
+  Sqlite3DbFixture()
   {
     boost::filesystem::create_directories(m_path);
+
     int result = sqlite3_open_v2((m_path / "sqlite3-statement.db").string().c_str(), &db,
                                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
 #ifdef NDN_CXX_DISABLE_SQLITE3_FS_LOCKING
@@ -52,21 +52,21 @@
     }
   }
 
-  ~Sqlite3StatementTestFixture()
+  ~Sqlite3DbFixture()
   {
     sqlite3_close(db);
     boost::filesystem::remove_all(m_path);
   }
 
-private:
-  boost::filesystem::path m_path;
+protected:
+  sqlite3* db = nullptr;
 
-public:
-  sqlite3* db;
+private:
+  const boost::filesystem::path m_path{UNIT_TESTS_TMPDIR};
 };
 
 BOOST_AUTO_TEST_SUITE(Util)
-BOOST_FIXTURE_TEST_SUITE(TestSqlite3Statement, Sqlite3StatementTestFixture)
+BOOST_FIXTURE_TEST_SUITE(TestSqlite3Statement, Sqlite3DbFixture)
 
 BOOST_AUTO_TEST_CASE(Basic)
 {
diff --git a/tests/unit/util/time-unit-test-clock.t.cpp b/tests/unit/util/time-unit-test-clock.t.cpp
index b65c9f9..f1be623 100644
--- a/tests/unit/util/time-unit-test-clock.t.cpp
+++ b/tests/unit/util/time-unit-test-clock.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2019 Regents of the University of California.
+ * Copyright (c) 2013-2020 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -23,7 +23,7 @@
 #include "ndn-cxx/util/scheduler.hpp"
 
 #include "tests/boost-test.hpp"
-#include "tests/unit/unit-test-time-fixture.hpp"
+#include "tests/unit/io-fixture.hpp"
 
 #include <boost/lexical_cast.hpp>
 #include <thread>
@@ -32,7 +32,7 @@
 namespace tests {
 
 BOOST_AUTO_TEST_SUITE(Util)
-BOOST_FIXTURE_TEST_SUITE(TestTimeUnitTestClock, UnitTestTimeFixture)
+BOOST_FIXTURE_TEST_SUITE(TestTimeUnitTestClock, ClockFixture)
 
 BOOST_AUTO_TEST_CASE(SystemClock)
 {
@@ -43,11 +43,11 @@
   BOOST_CHECK_EQUAL(time::system_clock::now().time_since_epoch(),
                     time::UnitTestClockTraits<time::system_clock>::getDefaultStartTime());
 
-  steadyClock->advance(1_day);
+  m_steadyClock->advance(1_day);
   BOOST_CHECK_EQUAL(time::system_clock::now().time_since_epoch(),
                     time::UnitTestClockTraits<time::system_clock>::getDefaultStartTime());
 
-  systemClock->advance(1_day);
+  m_systemClock->advance(1_day);
   BOOST_CHECK_GT(time::system_clock::now().time_since_epoch(),
                  time::UnitTestClockTraits<time::system_clock>::getDefaultStartTime());
 
@@ -55,7 +55,7 @@
     time::fromUnixTimestamp(time::milliseconds(1390966967032LL));
   BOOST_CHECK_GT(time::system_clock::now(), referenceTime);
 
-  systemClock->setNow(referenceTime.time_since_epoch());
+  m_systemClock->setNow(referenceTime.time_since_epoch());
   BOOST_CHECK_EQUAL(time::system_clock::now(), referenceTime);
 
   BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(time::system_clock::now()),
@@ -98,36 +98,36 @@
   BOOST_CHECK_EQUAL(time::steady_clock::now().time_since_epoch(),
                     time::steady_clock::duration::zero());
 
-  systemClock->advance(36500_days);
+  m_systemClock->advance(36500_days);
   BOOST_CHECK_EQUAL(time::steady_clock::now().time_since_epoch(),
                     time::steady_clock::duration::zero());
 
-  steadyClock->advance(100_ns);
+  m_steadyClock->advance(100_ns);
   BOOST_CHECK_EQUAL(time::steady_clock::now().time_since_epoch(), 100_ns);
 
-  steadyClock->advance(100_us);
+  m_steadyClock->advance(100_us);
   BOOST_CHECK_EQUAL(time::steady_clock::now().time_since_epoch(), 100100_ns);
 
-  steadyClock->setNow(1_ms);
+  m_steadyClock->setNow(1_ms);
   BOOST_CHECK_EQUAL(time::steady_clock::now().time_since_epoch(), 1000000_ns);
 
   BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(time::steady_clock::now()),
                     "1000000 nanoseconds since unit test beginning");
 }
 
-BOOST_AUTO_TEST_CASE(Scheduler)
+BOOST_FIXTURE_TEST_CASE(Scheduler, IoFixture)
 {
-  ndn::Scheduler scheduler(io);
+  ndn::Scheduler scheduler(m_io);
 
   bool hasFired = false;
   scheduler.schedule(100_s, [&] { hasFired = true; });
 
-  io.poll();
+  m_io.poll();
   BOOST_CHECK_EQUAL(hasFired, false);
 
-  steadyClock->advance(100_s);
+  m_steadyClock->advance(100_s);
 
-  io.poll();
+  m_io.poll();
   BOOST_CHECK_EQUAL(hasFired, true);
 }
 
diff --git a/tests/unit/wscript b/tests/unit/wscript
index e91ac7f..3fcf675 100644
--- a/tests/unit/wscript
+++ b/tests/unit/wscript
@@ -3,7 +3,7 @@
 top = '../../'
 
 def build(bld):
-    configPath = 'UNIT_TEST_CONFIG_PATH="%s"' % bld.bldnode.make_node('tmp-files')
+    tmpdir = 'UNIT_TESTS_TMPDIR="%s"' % bld.bldnode.make_node('tmp-files')
 
     # unit test objects
     srcFiles = bld.path.ant_glob('**/*.cpp', excl=['main.cpp',
@@ -21,7 +21,7 @@
                 features='pch',
                 headers='unit-tests-pch.hpp',
                 use='tests-common',
-                defines=[configPath])
+                defines=[tmpdir])
 
     # unit test binary
     bld.program(target=top + 'unit-tests',