tests: Converting test cases to use UnitTestClock

Change-Id: I3ceaf048cc60f9cdbf98ace43f96d5c81047efd0
diff --git a/tests/unit-tests/face.cpp b/tests/unit-tests/face.cpp
deleted file mode 100644
index 1d45910..0000000
--- a/tests/unit-tests/face.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2014 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 "face.hpp"
-#include "security/key-chain.hpp"
-
-#include "boost-test.hpp"
-#include "util/dummy-client-face.hpp"
-
-namespace ndn {
-namespace tests {
-
-using ndn::util::DummyClientFace;
-using ndn::util::makeDummyClientFace;
-
-BOOST_AUTO_TEST_SUITE(TestsFace)
-
-class Fixture
-{
-public:
-  Fixture()
-    : face(makeDummyClientFace())
-    , nData(0)
-    , nTimeouts(0)
-  {
-  }
-
-  void
-  onData()
-  {
-    ++nData;
-  }
-
-  void
-  onTimeout()
-  {
-    ++nTimeouts;
-  }
-
-public:
-  shared_ptr<DummyClientFace> face;
-  uint32_t nData;
-  uint32_t nTimeouts;
-};
-
-BOOST_FIXTURE_TEST_CASE(ExpressInterest, Fixture)
-{
-  face->expressInterest(Interest("/test/interest", time::seconds(10)),
-                        bind(&Fixture::onData, this),
-                        bind(&Fixture::onTimeout, this));
-  face->processEvents(time::milliseconds(100));
-
-  BOOST_CHECK_EQUAL(face->sentInterests.size(), 1);
-  BOOST_CHECK_EQUAL(face->sentDatas.size(), 0);
-}
-
-BOOST_FIXTURE_TEST_CASE(RemovePendingInterest, Fixture)
-{
-  const PendingInterestId* interestId =
-    face->expressInterest(Interest("/test/interest", time::seconds(10)),
-                          bind(&Fixture::onData, this),
-                          bind(&Fixture::onTimeout, this));
-
-  shared_ptr<Data> data = make_shared<Data>("/test/interest/replied");
-  const uint8_t buffer[] = "Hello, world!";
-  data->setContent(buffer, sizeof(buffer));
-  KeyChain keyChain;
-  keyChain.sign(*data);
-  face->receive(*data);
-
-  face->removePendingInterest(interestId);
-  face->processEvents(time::milliseconds(100));
-  BOOST_CHECK_EQUAL(nData, 0);
-  BOOST_CHECK_EQUAL(nTimeouts, 0);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // namespace tests
-} // namespace ndn
diff --git a/tests/unit-tests/management/test-nfd-controller.cpp b/tests/unit-tests/management/test-nfd-controller.cpp
index 98101f3..8555dde 100644
--- a/tests/unit-tests/management/test-nfd-controller.cpp
+++ b/tests/unit-tests/management/test-nfd-controller.cpp
@@ -26,6 +26,7 @@
 
 #include "boost-test.hpp"
 #include "util/dummy-client-face.hpp"
+#include "../unit-test-time-fixture.hpp"
 
 namespace ndn {
 namespace nfd {
@@ -36,11 +37,11 @@
 
 BOOST_AUTO_TEST_SUITE(ManagementTestNfdController)
 
-class CommandFixture
+class CommandFixture : public ndn::tests::UnitTestTimeFixture
 {
 protected:
   CommandFixture()
-    : face(makeDummyClientFace())
+    : face(makeDummyClientFace(io))
     , controller(*face, keyChain)
     , commandSucceedCallback(bind(&CommandFixture::onCommandSucceed, this, _1))
     , commandFailCallback(bind(&CommandFixture::onCommandFail, this, _1, _2))
@@ -83,7 +84,8 @@
                        parameters,
                        commandSucceedCallback,
                        commandFailCallback));
-  face->processEvents(time::milliseconds(1));
+
+  advanceClocks(time::milliseconds(1));
 
   BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);
   const Interest& requestInterest = face->sentInterests[0];
@@ -109,7 +111,8 @@
   responseData.setContent(responsePayload.wireEncode());
   keyChain.sign(responseData);
   face->receive(responseData);
-  face->processEvents(time::milliseconds(1));
+
+  advanceClocks(time::milliseconds(1));
 
   BOOST_CHECK_EQUAL(commandFailHistory.size(), 0);
   BOOST_REQUIRE_EQUAL(commandSucceedHistory.size(), 1);
@@ -140,7 +143,7 @@
                          parameters,
                          commandSucceedCallback,
                          commandFailCallback));
-  face->processEvents(time::milliseconds(1));
+  advanceClocks(time::milliseconds(1));
 
   BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);
   const Interest& requestInterest = face->sentInterests[0];
@@ -151,7 +154,7 @@
   responseData.setContent(responsePayload.wireEncode());
   keyChain.sign(responseData);
   face->receive(responseData);
-  face->processEvents(time::milliseconds(1));
+  advanceClocks(time::milliseconds(1));
 
   BOOST_CHECK_EQUAL(commandSucceedHistory.size(), 0);
   BOOST_REQUIRE_EQUAL(commandFailHistory.size(), 1);
@@ -167,7 +170,7 @@
                          parameters,
                          commandSucceedCallback,
                          commandFailCallback));
-  face->processEvents(time::milliseconds(1));
+  advanceClocks(time::milliseconds(1));
 
   BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);
   const Interest& requestInterest = face->sentInterests[0];
@@ -183,7 +186,7 @@
   responseData.setContent(responsePayload.wireEncode());
   keyChain.sign(responseData);
   face->receive(responseData);
-  face->processEvents(time::milliseconds(1));
+  advanceClocks(time::milliseconds(1));
 
   BOOST_CHECK_EQUAL(commandSucceedHistory.size(), 0);
   BOOST_REQUIRE_EQUAL(commandFailHistory.size(), 1);
@@ -203,7 +206,7 @@
                        commandSucceedCallback,
                        commandFailCallback,
                        options));
-  face->processEvents(time::milliseconds(1));
+  advanceClocks(time::milliseconds(1));
 
   BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);
   const Interest& requestInterest = face->sentInterests[0];
@@ -226,7 +229,7 @@
                        commandSucceedCallback,
                        commandFailCallback,
                        options));
-  face->processEvents(time::milliseconds(300));
+  advanceClocks(time::milliseconds(1), 101); // Face's PIT granularity is 100ms
 
   BOOST_REQUIRE_EQUAL(commandFailHistory.size(), 1);
   BOOST_CHECK_EQUAL(commandFailHistory[0].get<0>(), Controller::ERROR_TIMEOUT);
diff --git a/tests/unit-tests/security/test-certificate-cache.cpp b/tests/unit-tests/security/test-certificate-cache.cpp
index 54454e1..1524b1d 100644
--- a/tests/unit-tests/security/test-certificate-cache.cpp
+++ b/tests/unit-tests/security/test-certificate-cache.cpp
@@ -24,22 +24,20 @@
 #include "util/time-unit-test-clock.hpp"
 
 #include "boost-test.hpp"
+#include "../unit-test-time-fixture.hpp"
 
 namespace ndn {
 namespace tests {
 
 BOOST_AUTO_TEST_SUITE(SecurityTestCertificateCache)
 
-class UnitTestTimeFixture
+class CertificateCacheFixture : public UnitTestTimeFixture
 {
 public:
-  UnitTestTimeFixture()
-    : steadyClock(make_shared<time::UnitTestSteadyClock>())
-    , scheduler(io)
+  CertificateCacheFixture()
+    : scheduler(io)
     , cache(make_shared<CertificateCacheTtl>(ref(io), time::seconds(1)))
   {
-    time::setCustomClocks(steadyClock);
-
     cert1 = make_shared<IdentityCertificate>();
     Name certName1("/tmp/KEY/ksk-1/ID-CERT/1");
     cert1->setName(certName1);
@@ -54,15 +52,7 @@
     name2 = certName2.getPrefix(-1);
   }
 
-  ~UnitTestTimeFixture()
-  {
-    time::setCustomClocks(nullptr, nullptr);
-  }
-
 public:
-  shared_ptr<time::UnitTestSteadyClock> steadyClock;
-
-  boost::asio::io_service io;
   Scheduler scheduler;
 
   shared_ptr<CertificateCacheTtl> cache;
@@ -75,12 +65,12 @@
 };
 
 
-BOOST_FIXTURE_TEST_CASE(Expiration, UnitTestTimeFixture)
+BOOST_FIXTURE_TEST_CASE(Expiration, CertificateCacheFixture)
 {
   cache->insertCertificate(cert1);
   cache->insertCertificate(cert2);
 
-  io.poll();
+  advanceClocks(time::nanoseconds(0));
   BOOST_CHECK_EQUAL(cache->getSize(), 2);
 
   scheduler.scheduleEvent(time::milliseconds(200), [&] {
@@ -89,8 +79,7 @@
       BOOST_CHECK_EQUAL(static_cast<bool>(cache->getCertificate(name2)), true);
     });
 
-  steadyClock->advance(time::milliseconds(200));
-  io.poll();
+  advanceClocks(time::milliseconds(200));
 
   // cert1 should removed from the cache
   scheduler.scheduleEvent(time::milliseconds(700), [&] {
@@ -98,52 +87,47 @@
       BOOST_CHECK_EQUAL(static_cast<bool>(cache->getCertificate(name2)), true);
     });
 
-  steadyClock->advance(time::milliseconds(700));
-  io.poll();
+  advanceClocks(time::milliseconds(700));
   BOOST_CHECK_EQUAL(cache->getSize(), 1);
 
-  steadyClock->advance(time::milliseconds(700));
-  io.poll();
+  advanceClocks(time::milliseconds(700));
   BOOST_CHECK_EQUAL(cache->getSize(), 0);
 }
 
-BOOST_FIXTURE_TEST_CASE(TtlRefresh, UnitTestTimeFixture)
+BOOST_FIXTURE_TEST_CASE(TtlRefresh, CertificateCacheFixture)
 {
   cache->insertCertificate(cert1); // 500ms
 
-  io.poll();
+  advanceClocks(time::nanoseconds(0));
   BOOST_CHECK_EQUAL(cache->getSize(), 1);
 
-  steadyClock->advance(time::milliseconds(400));
-  io.poll();
+  advanceClocks(time::milliseconds(400));
   BOOST_CHECK_EQUAL(cache->getSize(), 1);
 
     // Refresh certificate in cache
   cache->insertCertificate(cert1); // +500ms
 
-  io.poll();
+  advanceClocks(time::nanoseconds(0));
   BOOST_CHECK_EQUAL(cache->getSize(), 1);
 
-  steadyClock->advance(time::milliseconds(400));
-  io.poll();
+  advanceClocks(time::milliseconds(400));
   BOOST_CHECK_EQUAL(cache->getSize(), 1);
 
-  steadyClock->advance(time::milliseconds(200));
-  io.poll();
+  advanceClocks(time::milliseconds(200));
   BOOST_CHECK_EQUAL(cache->getSize(), 0);
 }
 
-BOOST_FIXTURE_TEST_CASE(Reset, UnitTestTimeFixture)
+BOOST_FIXTURE_TEST_CASE(Reset, CertificateCacheFixture)
 {
   cache->insertCertificate(cert1);
   cache->insertCertificate(cert2);
 
-  io.poll();
+  advanceClocks(time::nanoseconds(0));
   BOOST_CHECK_EQUAL(cache->getSize(), 2);
 
   cache->reset();
 
-  io.poll();
+  advanceClocks(time::nanoseconds(0));
   BOOST_CHECK_EQUAL(cache->getSize(), 0);
 }
 
diff --git a/tests/unit-tests/test-faces.cpp b/tests/unit-tests/test-faces.cpp
index 84982a0..57effc9 100644
--- a/tests/unit-tests/test-faces.cpp
+++ b/tests/unit-tests/test-faces.cpp
@@ -22,9 +22,11 @@
 #include "face.hpp"
 #include "util/scheduler.hpp"
 #include "security/key-chain.hpp"
+#include "util/dummy-client-face.hpp"
 
 #include "boost-test.hpp"
-#include "util/dummy-client-face.hpp"
+#include "unit-test-time-fixture.hpp"
+#include "test-make-interest-data.hpp"
 
 namespace ndn {
 namespace tests {
@@ -32,108 +34,17 @@
 using ndn::util::DummyClientFace;
 using ndn::util::makeDummyClientFace;
 
-class FacesFixture
+class FacesFixture : public UnitTestTimeFixture
 {
 public:
+  explicit
   FacesFixture(bool enableRegistrationReply = true)
-    : nData(0)
-    , nTimeouts(0)
-    , nInInterests(0)
-    , nInInterests2(0)
-    , nRegSuccesses(0)
-    , nRegFailures(0)
-    , nUnregSuccesses(0)
-    , nUnregFailures(0)
+    : face(makeDummyClientFace(io, { true, enableRegistrationReply }))
   {
-    DummyClientFace::Options options { true, enableRegistrationReply };
-    this->face = makeDummyClientFace(io, options);
   }
 
-  void
-  onData()
-  {
-    ++nData;
-  }
-
-  void
-  onTimeout()
-  {
-    ++nTimeouts;
-  }
-
-  void
-  onInterest(Face& face,
-             const Name&, const Interest&)
-  {
-    ++nInInterests;
-  }
-
-  void
-  onInterest2(Face& face,
-              const Name&, const Interest&)
-  {
-    ++nInInterests2;
-  }
-
-  void
-  onInterestRegex(Face& face,
-                  const InterestFilter&, const Interest&)
-  {
-    ++nInInterests;
-  }
-
-  void
-  onInterestRegexError(Face& face,
-                       const Name&, const Interest&)
-  {
-    BOOST_FAIL("InterestFilter::Error should have been triggered");
-  }
-
-  void
-  onRegSucceeded()
-  {
-    ++nRegSuccesses;
-  }
-
-  void
-  onRegFailed()
-  {
-    ++nRegFailures;
-  }
-
-  void
-  onUnregSucceeded()
-  {
-    ++nUnregSuccesses;
-  }
-
-  void
-  onUnregFailed()
-  {
-    ++nUnregFailures;
-  }
-
-  shared_ptr<Data>
-  makeData(const Name& name)
-  {
-    shared_ptr<Data> data = make_shared<Data>("/Hello/World/!");
-    static KeyChain keyChain;
-    keyChain.signWithSha256(*data);
-    return data;
-  }
-
-  boost::asio::io_service io;
+public:
   shared_ptr<DummyClientFace> face;
-
-  uint32_t nData;
-  uint32_t nTimeouts;
-
-  uint32_t nInInterests;
-  uint32_t nInInterests2;
-  uint32_t nRegSuccesses;
-  uint32_t nRegFailures;
-  uint32_t nUnregSuccesses;
-  uint32_t nUnregFailures;
 };
 
 class FacesNoRegistrationReplyFixture : public FacesFixture
@@ -149,182 +60,230 @@
 
 BOOST_AUTO_TEST_CASE(ExpressInterestData)
 {
+  size_t nData = 0;
   face->expressInterest(Interest("/Hello/World", time::milliseconds(50)),
-                        bind(&FacesFixture::onData, this),
-                        bind(&FacesFixture::onTimeout, this));
+                        [&] (const Interest& i, const Data& d) {
+                          BOOST_CHECK(i.getName().isPrefixOf(d.getName()));
+                          ++nData;
+                        },
+                        bind([] {
+                            BOOST_FAIL("Unexpected timeout");
+                          }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
+  advanceClocks(time::milliseconds(10));
 
-  face->receive(*makeData("/Hello/World/!"));
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(200)));
+  face->receive(*util::makeData("/Bye/World/!"));
+  face->receive(*util::makeData("/Hello/World/!"));
+
+  advanceClocks(time::milliseconds(10), 100);
 
   BOOST_CHECK_EQUAL(nData, 1);
-  BOOST_CHECK_EQUAL(nTimeouts, 0);
+  BOOST_CHECK_EQUAL(face->sentInterests.size(), 1);
+  BOOST_CHECK_EQUAL(face->sentDatas.size(), 0);
 }
 
 BOOST_AUTO_TEST_CASE(ExpressInterestTimeout)
 {
+  size_t nTimeouts = 0;
   face->expressInterest(Interest("/Hello/World", time::milliseconds(50)),
-                        bind(&FacesFixture::onData, this),
-                        bind(&FacesFixture::onTimeout, this));
+                        bind([] {
+                            BOOST_FAIL("Unexpected data");
+                          }),
+                        bind([&nTimeouts] {
+                            ++nTimeouts;
+                          }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(200)));
+  advanceClocks(time::milliseconds(10), 100);
 
-  BOOST_CHECK_EQUAL(nData, 0);
   BOOST_CHECK_EQUAL(nTimeouts, 1);
+  BOOST_CHECK_EQUAL(face->sentInterests.size(), 1);
+  BOOST_CHECK_EQUAL(face->sentDatas.size(), 0);
 }
 
-BOOST_AUTO_TEST_CASE(SetFilter)
+BOOST_AUTO_TEST_CASE(RemovePendingInterest)
 {
-  face->setInterestFilter("/Hello/World",
-                          bind(&FacesFixture::onInterest, this, ref(*face), _1, _2),
-                          RegisterPrefixSuccessCallback(),
-                          bind(&FacesFixture::onRegFailed, this));
+  const PendingInterestId* interestId =
+    face->expressInterest(Interest("/Hello/World", time::milliseconds(50)),
+                          bind([] {
+                              BOOST_FAIL("Unexpected data");
+                            }),
+                          bind([] {
+                              BOOST_FAIL("Unexpected timeout");
+                            }));
+  advanceClocks(time::milliseconds(10));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
+  face->removePendingInterest(interestId);
+  advanceClocks(time::milliseconds(10));
 
-  face->receive(Interest("/Hello/World/!"));
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
-
-  BOOST_CHECK_EQUAL(nRegFailures, 0);
-  BOOST_CHECK_EQUAL(nInInterests, 1);
-}
-
-BOOST_FIXTURE_TEST_CASE(SetFilterFail, FacesNoRegistrationReplyFixture)
-{
-  // don't enable registration reply
-
-  face->setInterestFilter("/Hello/World",
-                          bind(&FacesFixture::onInterest, this, ref(*face), _1, _2),
-                          RegisterPrefixSuccessCallback(),
-                          bind(&FacesFixture::onRegFailed, this));
-
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(11000)));
-
-  BOOST_CHECK_EQUAL(nRegFailures, 1);
+  face->receive(*util::makeData("/Hello/World/!"));
+  advanceClocks(time::milliseconds(10), 100);
 }
 
 BOOST_AUTO_TEST_CASE(SetUnsetInterestFilter)
 {
+  size_t nInterests = 0;
+  size_t nRegs = 0;
   const RegisteredPrefixId* regPrefixId =
-    face->setInterestFilter(InterestFilter("/Hello/World"),
-                            bind(&FacesFixture::onInterest, this,
-                                 ref(*face), _1, _2),
-                            RegisterPrefixSuccessCallback(),
-                            bind(&FacesFixture::onRegFailed, this));
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
+    face->setInterestFilter("/Hello/World",
+                            bind([&nInterests] { ++nInterests; }),
+                            bind([&nRegs] { ++nRegs; }),
+                            bind([] {
+                                BOOST_FAIL("Unexpected setInterestFilter failure");
+                              }));
+  advanceClocks(time::milliseconds(10), 10);
+  BOOST_CHECK_EQUAL(nRegs, 1);
+  BOOST_CHECK_EQUAL(nInterests, 0);
 
   face->receive(Interest("/Hello/World/!"));
-  BOOST_CHECK_EQUAL(nInInterests, 1);
+  advanceClocks(time::milliseconds(10), 10);
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
+  BOOST_CHECK_EQUAL(nRegs, 1);
+  BOOST_CHECK_EQUAL(nInterests, 1);
 
-  face->receive(Interest("/Hello/World/!"));
-  BOOST_CHECK_EQUAL(nInInterests, 2);
+  face->receive(Interest("/Bye/World/!"));
+  advanceClocks(time::milliseconds(10000), 10);
+  BOOST_CHECK_EQUAL(nInterests, 1);
 
+  face->receive(Interest("/Hello/World/!/2"));
+  advanceClocks(time::milliseconds(10), 10);
+  BOOST_CHECK_EQUAL(nInterests, 2);
+
+  // removing filter
   face->unsetInterestFilter(regPrefixId);
+  advanceClocks(time::milliseconds(10), 10);
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
+  face->receive(Interest("/Hello/World/!/3"));
+  BOOST_CHECK_EQUAL(nInterests, 2);
 
-  face->receive(Interest("/Hello/World/!"));
-  BOOST_CHECK_EQUAL(nInInterests, 2);
+  face->unsetInterestFilter(static_cast<const RegisteredPrefixId*>(0));
+  advanceClocks(time::milliseconds(10), 10);
 
-  BOOST_CHECK_NO_THROW(face->unsetInterestFilter(static_cast<const RegisteredPrefixId*>(0)));
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
+  face->unsetInterestFilter(static_cast<const InterestFilterId*>(0));
+  advanceClocks(time::milliseconds(10), 10);
+}
 
-  BOOST_CHECK_NO_THROW(face->unsetInterestFilter(static_cast<const InterestFilterId*>(0)));
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
+BOOST_FIXTURE_TEST_CASE(SetInterestFilterFail, FacesNoRegistrationReplyFixture)
+{
+  // don't enable registration reply
+  size_t nRegFailed = 0;
+  face->setInterestFilter("/Hello/World",
+                          bind([] {
+                              BOOST_FAIL("Unexpected Interest");
+                            }),
+                          bind([] {
+                              BOOST_FAIL("Unexpected success of setInterestFilter");
+                            }),
+                          bind([&nRegFailed] {
+                              ++nRegFailed;
+                            }));
+
+  advanceClocks(time::milliseconds(10), 10);
+  BOOST_CHECK_EQUAL(nRegFailed, 0);
+
+  advanceClocks(time::milliseconds(1000), 10);
+  BOOST_CHECK_EQUAL(nRegFailed, 1);
 }
 
 BOOST_AUTO_TEST_CASE(RegisterUnregisterPrefix)
 {
+  size_t nRegSuccesses = 0;
   const RegisteredPrefixId* regPrefixId =
     face->registerPrefix("/Hello/World",
-                         bind(&FacesFixture::onRegSucceeded, this),
-                         bind(&FacesFixture::onRegFailed, this));
+                         bind([&nRegSuccesses] { ++nRegSuccesses; }),
+                         bind([] {
+                             BOOST_FAIL("Unexpected registerPrefix failure");
+                           }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
-  BOOST_CHECK_EQUAL(nRegFailures, 0);
+  advanceClocks(time::milliseconds(10), 10);
   BOOST_CHECK_EQUAL(nRegSuccesses, 1);
 
+  size_t nUnregSuccesses = 0;
   face->unregisterPrefix(regPrefixId,
-                         bind(&FacesFixture::onUnregSucceeded, this),
-                         bind(&FacesFixture::onUnregFailed, this));
+                         bind([&nUnregSuccesses] { ++nUnregSuccesses; }),
+                         bind([] {
+                             BOOST_FAIL("Unexpected unregisterPrefix failure");
+                           }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
-  BOOST_CHECK_EQUAL(nUnregFailures, 0);
+  advanceClocks(time::milliseconds(10), 10);
   BOOST_CHECK_EQUAL(nUnregSuccesses, 1);
-
 }
 
-BOOST_AUTO_TEST_CASE(SeTwoSimilarFilters)
+BOOST_FIXTURE_TEST_CASE(RegisterUnregisterPrefixFail, FacesNoRegistrationReplyFixture)
 {
-  face->setInterestFilter("/Hello/World",
-                          bind(&FacesFixture::onInterest, this, ref(*face), _1, _2),
-                          RegisterPrefixSuccessCallback(),
-                          bind(&FacesFixture::onRegFailed, this));
+  size_t nRegFailures = 0;
+  face->registerPrefix("/Hello/World",
+                       bind([] {
+                           BOOST_FAIL("Unexpected registerPrefix success");
+                         }),
+                       bind([&nRegFailures] { ++nRegFailures; }));
 
+  advanceClocks(time::milliseconds(1000), 100);
+  BOOST_CHECK_EQUAL(nRegFailures, 1);
+}
+
+BOOST_AUTO_TEST_CASE(SimilarFilters)
+{
+  size_t nInInterests1 = 0;
+  face->setInterestFilter("/Hello/World",
+                          bind([&nInInterests1] { ++nInInterests1; }),
+                          RegisterPrefixSuccessCallback(),
+                          bind([] {
+                              BOOST_FAIL("Unexpected setInterestFilter failure");
+                            }));
+
+  size_t nInInterests2 = 0;
   face->setInterestFilter("/Hello",
-                          bind(&FacesFixture::onInterest2, this, ref(*face), _1, _2),
+                          bind([&nInInterests2] { ++nInInterests2; }),
                           RegisterPrefixSuccessCallback(),
-                          bind(&FacesFixture::onRegFailed, this));
+                          bind([] {
+                              BOOST_FAIL("Unexpected setInterestFilter failure");
+                            }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
-
-  face->receive(Interest("/Hello/World/!"));
-
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
-
-  BOOST_CHECK_EQUAL(nRegFailures, 0);
-  BOOST_CHECK_EQUAL(nInInterests, 1);
-  BOOST_CHECK_EQUAL(nInInterests2, 1);
-}
-
-BOOST_AUTO_TEST_CASE(SetTwoDifferentFilters)
-{
-  face->setInterestFilter("/Hello/World",
-                          bind(&FacesFixture::onInterest, this, ref(*face), _1, _2),
-                          RegisterPrefixSuccessCallback(),
-                          bind(&FacesFixture::onRegFailed, this));
-
+  size_t nInInterests3 = 0;
   face->setInterestFilter("/Los/Angeles/Lakers",
-                          bind(&FacesFixture::onInterest2, this, ref(*face), _1, _2),
+                          bind([&nInInterests3] { ++nInInterests3; }),
                           RegisterPrefixSuccessCallback(),
-                          bind(&FacesFixture::onRegFailed, this));
+                          bind([] {
+                              BOOST_FAIL("Unexpected setInterestFilter failure");
+                            }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
+  advanceClocks(time::milliseconds(10), 10);
 
   face->receive(Interest("/Hello/World/!"));
+  advanceClocks(time::milliseconds(10), 10);
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
-
-  BOOST_CHECK_EQUAL(nRegFailures, 0);
-  BOOST_CHECK_EQUAL(nInInterests, 1);
-  BOOST_CHECK_EQUAL(nInInterests2, 0);
+  BOOST_CHECK_EQUAL(nInInterests1, 1);
+  BOOST_CHECK_EQUAL(nInInterests2, 1);
+  BOOST_CHECK_EQUAL(nInInterests3, 0);
 }
 
 BOOST_AUTO_TEST_CASE(SetRegexFilterError)
 {
   face->setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
-                          bind(&FacesFixture::onInterestRegexError, this,
-                               ref(*face), _1, _2),
+                          [] (const Name&, const Interest&) {
+                            BOOST_FAIL("InterestFilter::Error should have been triggered");
+                          },
                           RegisterPrefixSuccessCallback(),
-                          bind(&FacesFixture::onRegFailed, this));
+                          bind([] {
+                              BOOST_FAIL("Unexpected setInterestFilter failure");
+                            }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
+  advanceClocks(time::milliseconds(10), 10);
 
   BOOST_REQUIRE_THROW(face->receive(Interest("/Hello/World/XXX/b/c")), InterestFilter::Error);
 }
 
 BOOST_AUTO_TEST_CASE(SetRegexFilter)
 {
+  size_t nInInterests = 0;
   face->setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
-                          bind(&FacesFixture::onInterestRegex, this,
-                               ref(*face), _1, _2),
+                          bind([&nInInterests] { ++nInInterests; }),
                           RegisterPrefixSuccessCallback(),
-                          bind(&FacesFixture::onRegFailed, this));
+                          bind([] {
+                              BOOST_FAIL("Unexpected setInterestFilter failure");
+                            }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(-100)));
+  advanceClocks(time::milliseconds(10), 10);
 
   face->receive(Interest("/Hello/World/a"));     // shouldn't match
   BOOST_CHECK_EQUAL(nInInterests, 0);
@@ -339,19 +298,20 @@
   BOOST_CHECK_EQUAL(nInInterests, 2);
 }
 
-
 BOOST_AUTO_TEST_CASE(SetRegexFilterAndRegister)
 {
+  size_t nInInterests = 0;
   face->setInterestFilter(InterestFilter("/Hello/World", "<><b><c>?"),
-                          bind(&FacesFixture::onInterestRegex, this,
-                               ref(*face), _1, _2));
+                          bind([&nInInterests] { ++nInInterests; }));
 
+  size_t nRegSuccesses = 0;
   face->registerPrefix("/Hello/World",
-                       bind(&FacesFixture::onRegSucceeded, this),
-                       bind(&FacesFixture::onRegFailed, this));
+                       bind([&nRegSuccesses] { ++nRegSuccesses; }),
+                       bind([] {
+                           BOOST_FAIL("Unexpected setInterestFilter failure");
+                         }));
 
-  BOOST_REQUIRE_NO_THROW(face->processEvents(time::milliseconds(100)));
-  BOOST_CHECK_EQUAL(nRegFailures, 0);
+  advanceClocks(time::milliseconds(10), 10);
   BOOST_CHECK_EQUAL(nRegSuccesses, 1);
 
   face->receive(Interest("/Hello/World/a")); // shouldn't match
@@ -371,17 +331,18 @@
 {
   face->processEvents(time::milliseconds(-1)); // io_service::reset()/poll() inside
 
+  size_t nRegSuccesses = 0;
   face->registerPrefix("/Hello/World",
-                       bind(&FacesFixture::onRegSucceeded, this),
-                       bind(&FacesFixture::onRegFailed, this));
+                       bind([&nRegSuccesses] { ++nRegSuccesses; }),
+                       bind([] {
+                           BOOST_FAIL("Unexpected setInterestFilter failure");
+                         }));
 
   // io_service::poll() without reset
   face->getIoService().poll();
-  BOOST_CHECK_EQUAL(nRegFailures, 0);
   BOOST_CHECK_EQUAL(nRegSuccesses, 0);
 
   face->processEvents(time::milliseconds(-1)); // io_service::reset()/poll() inside
-  BOOST_CHECK_EQUAL(nRegFailures, 0);
   BOOST_CHECK_EQUAL(nRegSuccesses, 1);
 }
 
diff --git a/tests/unit-tests/unit-test-time-fixture.hpp b/tests/unit-tests/unit-test-time-fixture.hpp
new file mode 100644
index 0000000..606ed53
--- /dev/null
+++ b/tests/unit-tests/unit-test-time-fixture.hpp
@@ -0,0 +1,68 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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_TESTS_UNIT_TEST_TIME_FIXTURE_HPP
+#define NDN_TESTS_UNIT_TESTS_UNIT_TEST_TIME_FIXTURE_HPP
+
+#include "util/time-unit-test-clock.hpp"
+#include <boost/asio.hpp>
+
+namespace ndn {
+namespace tests {
+
+class UnitTestTimeFixture
+{
+public:
+  UnitTestTimeFixture()
+    : steadyClock(make_shared<time::UnitTestSteadyClock>())
+    , systemClock(make_shared<time::UnitTestSystemClock>())
+  {
+    time::setCustomClocks(steadyClock, systemClock);
+  }
+
+  ~UnitTestTimeFixture()
+  {
+    time::setCustomClocks(nullptr, nullptr);
+  }
+
+  void
+  advanceClocks(const time::nanoseconds& tick, size_t nTicks = 1)
+  {
+    for (size_t i = 0; i < nTicks; ++i) {
+      steadyClock->advance(tick);
+      systemClock->advance(tick);
+
+      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_TESTS_UNIT_TEST_TIME_FIXTURE_HPP
diff --git a/tests/unit-tests/util/notification-stream.cpp b/tests/unit-tests/util/notification-stream.cpp
index adba5c7..4b6d43d 100644
--- a/tests/unit-tests/util/notification-stream.cpp
+++ b/tests/unit-tests/util/notification-stream.cpp
@@ -47,26 +47,29 @@
 
 #include "util/notification-stream.hpp"
 #include "simple-notification.hpp"
+#include "util/dummy-client-face.hpp"
 
 #include "boost-test.hpp"
-#include "util/dummy-client-face.hpp"
+#include "../unit-test-time-fixture.hpp"
 
 namespace ndn {
 namespace util {
 namespace tests {
 
-BOOST_AUTO_TEST_SUITE(UtilNotificationStream)
+BOOST_FIXTURE_TEST_SUITE(UtilNotificationStream, ndn::tests::UnitTestTimeFixture)
 
 BOOST_AUTO_TEST_CASE(Post)
 {
-  shared_ptr<DummyClientFace> face = makeDummyClientFace();
+  shared_ptr<DummyClientFace> face = makeDummyClientFace(io);
   ndn::KeyChain keyChain;
   util::NotificationStream<SimpleNotification> notificationStream(*face,
     "/localhost/nfd/NotificationStreamTest", keyChain);
 
   SimpleNotification event1("msg1");
   notificationStream.postNotification(event1);
-  face->processEvents();
+
+  advanceClocks(time::milliseconds(1));
+
   BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 1);
   BOOST_CHECK_EQUAL(face->sentDatas[0].getName(),
                     "/localhost/nfd/NotificationStreamTest/%FE%00");
@@ -76,7 +79,9 @@
 
   SimpleNotification event2("msg2");
   notificationStream.postNotification(event2);
-  face->processEvents();
+
+  advanceClocks(time::milliseconds(1));
+
   BOOST_REQUIRE_EQUAL(face->sentDatas.size(), 2);
   BOOST_CHECK_EQUAL(face->sentDatas[1].getName(),
                     "/localhost/nfd/NotificationStreamTest/%FE%01");
diff --git a/tests/unit-tests/util/notification-subscriber.cpp b/tests/unit-tests/util/notification-subscriber.cpp
index 9d7ab65..96f5bf4 100644
--- a/tests/unit-tests/util/notification-subscriber.cpp
+++ b/tests/unit-tests/util/notification-subscriber.cpp
@@ -48,10 +48,10 @@
 #include "util/notification-subscriber.hpp"
 #include "util/notification-stream.hpp"
 #include "simple-notification.hpp"
+#include "util/dummy-client-face.hpp"
 
 #include "boost-test.hpp"
-#include <boost/asio.hpp>
-#include "util/dummy-client-face.hpp"
+#include "../unit-test-time-fixture.hpp"
 
 namespace ndn {
 namespace util {
@@ -59,14 +59,14 @@
 
 BOOST_AUTO_TEST_SUITE(UtilNotificationSubscriber)
 
-class EndToEndFixture
+class EndToEndFixture : public ndn::tests::UnitTestTimeFixture
 {
 public:
   EndToEndFixture()
     : streamPrefix("ndn:/NotificationSubscriberTest")
-    , publisherFace(makeDummyClientFace(ioService))
+    , publisherFace(makeDummyClientFace(io))
     , notificationStream(*publisherFace, streamPrefix, publisherKeyChain)
-    , subscriberFace(makeDummyClientFace(ioService))
+    , subscriberFace(makeDummyClientFace(io))
     , subscriber(*subscriberFace, streamPrefix, time::seconds(1))
   {
   }
@@ -80,7 +80,7 @@
     SimpleNotification notification(msg);
     notificationStream.postNotification(notification);
 
-    publisherFace->processEvents(time::milliseconds(100));
+    advanceClocks(time::milliseconds(1));
 
     BOOST_REQUIRE_EQUAL(publisherFace->sentDatas.size(), 1);
 
@@ -149,7 +149,6 @@
   }
 
 protected:
-  boost::asio::io_service ioService;
   Name streamPrefix;
   shared_ptr<DummyClientFace> publisherFace;
   ndn::KeyChain publisherKeyChain;
@@ -178,34 +177,34 @@
 
   // not received when subscriber is not running
   this->deliverNotification("n1");
-  subscriberFace->processEvents(time::milliseconds(100));
+  advanceClocks(time::milliseconds(1));
   BOOST_CHECK(lastNotification.getMessage().empty());
   BOOST_CHECK_EQUAL(subscriberFace->sentInterests.size(), 0);
 
   subscriberFace->sentInterests.clear();
   subscriber.start();
-  subscriberFace->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1));
   BOOST_REQUIRE_EQUAL(subscriber.isRunning(), true);
   BOOST_CHECK(this->hasInitialRequest());
 
   // respond to initial request
   subscriberFace->sentInterests.clear();
   this->deliverNotification("n2");
-  subscriberFace->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1));
   BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n2");
   BOOST_CHECK_EQUAL(this->getRequestSeqNo(), lastDeliveredSeqNo + 1);
 
   // respond to continuation request
   subscriberFace->sentInterests.clear();
   this->deliverNotification("n3");
-  subscriberFace->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1));
   BOOST_CHECK_EQUAL(lastNotification.getMessage(), "n3");
   BOOST_CHECK_EQUAL(this->getRequestSeqNo(), lastDeliveredSeqNo + 1);
 
   // timeout
   subscriberFace->sentInterests.clear();
   lastNotification.setMessage("");
-  subscriberFace->processEvents(2 * subscriber.getInterestLifetime());
+  advanceClocks(subscriber.getInterestLifetime(), 2);
   BOOST_CHECK(lastNotification.getMessage().empty());
   BOOST_CHECK_EQUAL(hasTimeout, true);
   BOOST_CHECK(this->hasInitialRequest());
@@ -218,7 +217,7 @@
   subscriberFace->receive(wrongData);
   subscriberFace->sentInterests.clear();
   lastNotification.setMessage("");
-  subscriberFace->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1));
   BOOST_CHECK(lastNotification.getMessage().empty());
   BOOST_CHECK_EQUAL(lastDecodeErrorData.getName(), wrongName);
   BOOST_CHECK(this->hasInitialRequest());
@@ -227,7 +226,7 @@
   subscriberFace->sentInterests.clear();
   lastNotification.setMessage("");
   this->deliverNotification("\x07n4");
-  subscriberFace->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1));
   BOOST_CHECK(lastNotification.getMessage().empty());
   BOOST_CHECK(this->hasInitialRequest());
 
@@ -235,7 +234,7 @@
   subscriber.onNotification += bind(&EndToEndFixture::clearNotificationHandlers, this);
   subscriberFace->sentInterests.clear();
   this->deliverNotification("n5");
-  subscriberFace->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1));
   BOOST_CHECK_EQUAL(subscriberFace->sentInterests.size(), 0);
 }
 
diff --git a/tests/unit-tests/util/segment-fetcher.cpp b/tests/unit-tests/util/segment-fetcher.cpp
index 3a9fc5f..15d7831 100644
--- a/tests/unit-tests/util/segment-fetcher.cpp
+++ b/tests/unit-tests/util/segment-fetcher.cpp
@@ -24,6 +24,7 @@
 #include "boost-test.hpp"
 #include "util/dummy-client-face.hpp"
 #include "security/key-chain.hpp"
+#include "../unit-test-time-fixture.hpp"
 
 namespace ndn {
 namespace util {
@@ -31,11 +32,11 @@
 
 BOOST_AUTO_TEST_SUITE(UtilSegmentFetcher)
 
-class Fixture
+class Fixture : public ndn::tests::UnitTestTimeFixture
 {
 public:
   Fixture()
-    : face(makeDummyClientFace())
+    : face(makeDummyClientFace(io))
     , nErrors(0)
     , nDatas(0)
     , dataSize(0)
@@ -89,10 +90,9 @@
                         bind(&Fixture::onData, this, _1),
                         bind(&Fixture::onError, this, _1));
 
-  face->processEvents(time::seconds(1));
+  advanceClocks(time::milliseconds(1), 99);
 
-  BOOST_CHECK_EQUAL(nErrors, 1);
-  BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
+  BOOST_CHECK_EQUAL(nErrors, 0);
   BOOST_CHECK_EQUAL(nDatas, 0);
   BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);
   BOOST_CHECK_EQUAL(face->sentDatas.size(), 0);
@@ -101,21 +101,27 @@
   BOOST_CHECK_EQUAL(interest.getName(), "/hello/world");
   BOOST_CHECK_EQUAL(interest.getMustBeFresh(), true);
   BOOST_CHECK_EQUAL(interest.getChildSelector(), 1);
+
+  advanceClocks(time::milliseconds(1), 2);
+
+  BOOST_CHECK_EQUAL(nErrors, 1);
+  BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::INTEREST_TIMEOUT));
+  BOOST_REQUIRE_EQUAL(face->sentInterests.size(), 1);
+  BOOST_CHECK_EQUAL(face->sentDatas.size(), 0);
 }
 
 
 BOOST_FIXTURE_TEST_CASE(Basic, Fixture)
 {
-
   SegmentFetcher::fetch(*face, Interest("/hello/world", time::seconds(1000)),
                         DontVerifySegment(),
                         bind(&Fixture::onData, this, _1),
                         bind(&Fixture::onError, this, _1));
 
+  advanceClocks(time::milliseconds(1), 10);
 
-  face->processEvents(time::milliseconds(-100));
   face->receive(*makeData("/hello/world/version0", 0, true));
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
 
   BOOST_CHECK_EQUAL(nErrors, 0);
   BOOST_CHECK_EQUAL(nDatas, 1);
@@ -139,7 +145,7 @@
                         bind(&Fixture::onData, this, _1),
                         bind(&Fixture::onError, this, _1));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
 
   const uint8_t buffer[] = "Hello, world!";
 
@@ -148,7 +154,7 @@
   keyChain.sign(*data);
 
   face->receive(*data);
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
 
   BOOST_CHECK_EQUAL(nErrors, 1);
   BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::DATA_HAS_NO_SEGMENT));
@@ -169,9 +175,9 @@
                         bind(&Fixture::onData, this, _1),
                         bind(&Fixture::onError, this, _1));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
   face->receive(*makeData("/hello/world/version0", 0, true));
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
 
   BOOST_CHECK_EQUAL(nErrors, 1);
   BOOST_CHECK_EQUAL(lastError, static_cast<uint32_t>(SegmentFetcher::SEGMENT_VERIFICATION_FAIL));
@@ -188,16 +194,16 @@
                         bind(&Fixture::onData, this, _1),
                         bind(&Fixture::onError, this, _1));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
   face->receive(*makeData("/hello/world/version0", 0, false));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
   face->receive(*makeData("/hello/world/version0", 1, false));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
   face->receive(*makeData("/hello/world/version0", 2, true));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
 
   BOOST_CHECK_EQUAL(nErrors, 0);
   BOOST_CHECK_EQUAL(nDatas, 1);
@@ -238,19 +244,19 @@
                         bind(&Fixture::onData, this, _1),
                         bind(&Fixture::onError, this, _1));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
   face->receive(*makeData("/hello/world/version0", 1, false));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
   face->receive(*makeData("/hello/world/version0", 0, false));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
   face->receive(*makeData("/hello/world/version0", 1, false));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
   face->receive(*makeData("/hello/world/version0", 2, true));
 
-  face->processEvents(time::milliseconds(-100));
+  advanceClocks(time::milliseconds(1), 10);
 
   BOOST_CHECK_EQUAL(nErrors, 0);
   BOOST_CHECK_EQUAL(nDatas, 1);
diff --git a/tests/unit-tests/util/test-scheduler.cpp b/tests/unit-tests/util/test-scheduler.cpp
index 04d4f99..c8c8179 100644
--- a/tests/unit-tests/util/test-scheduler.cpp
+++ b/tests/unit-tests/util/test-scheduler.cpp
@@ -22,253 +22,186 @@
 #include "util/scheduler.hpp"
 
 #include "boost-test.hpp"
+#include "../unit-test-time-fixture.hpp"
 
 namespace ndn {
+namespace tests {
 
-BOOST_AUTO_TEST_SUITE(UtilTestScheduler)
+BOOST_FIXTURE_TEST_SUITE(UtilTestScheduler, UnitTestTimeFixture)
 
-struct SchedulerFixture
+BOOST_AUTO_TEST_CASE(Events)
 {
-  SchedulerFixture()
-    : count1(0)
-    , count2(0)
-    , count3(0)
-  {
-  }
-
-  void
-  event1()
-  {
-    BOOST_CHECK_EQUAL(count3, 1);
-    ++count1;
-  }
-
-  void
-  event2()
-  {
-    ++count2;
-  }
-
-  void
-  event3()
-  {
-    BOOST_CHECK_EQUAL(count1, 0);
-    ++count3;
-  }
-
-  int count1;
-  int count2;
-  int count3;
-};
-
-BOOST_FIXTURE_TEST_CASE(Events, SchedulerFixture)
-{
-  boost::asio::io_service io;
+  size_t count1 = 0;
+  size_t count2 = 0;
 
   Scheduler scheduler(io);
-  scheduler.scheduleEvent(time::milliseconds(500), bind(&SchedulerFixture::event1, this));
+  scheduler.scheduleEvent(time::milliseconds(500), [&] {
+      ++count1;
+      BOOST_CHECK_EQUAL(count2, 1);
+    });
 
-  EventId i = scheduler.scheduleEvent(time::seconds(1), bind(&SchedulerFixture::event2, this));
+  EventId i = scheduler.scheduleEvent(time::seconds(1), [&] {
+      BOOST_ERROR("This event should not have been fired");
+    });
   scheduler.cancelEvent(i);
 
-  scheduler.scheduleEvent(time::milliseconds(250), bind(&SchedulerFixture::event3, this));
+  scheduler.scheduleEvent(time::milliseconds(250), [&] {
+      BOOST_CHECK_EQUAL(count1, 0);
+      ++count2;
+    });
 
-  i = scheduler.scheduleEvent(time::milliseconds(50), bind(&SchedulerFixture::event2, this));
+  i = scheduler.scheduleEvent(time::milliseconds(50), [&] {
+      BOOST_ERROR("This event should not have been fired");
+    });
   scheduler.cancelEvent(i);
 
-  io.run();
-
+  advanceClocks(time::milliseconds(1), 1000);
   BOOST_CHECK_EQUAL(count1, 1);
-  BOOST_CHECK_EQUAL(count2, 0);
-  BOOST_CHECK_EQUAL(count3, 1);
+  BOOST_CHECK_EQUAL(count2, 1);
 }
 
 BOOST_AUTO_TEST_CASE(CancelEmptyEvent)
 {
-  boost::asio::io_service io;
   Scheduler scheduler(io);
 
   EventId i;
   scheduler.cancelEvent(i);
 }
 
-struct SelfCancelFixture
+BOOST_AUTO_TEST_CASE(SelfCancel)
 {
-  SelfCancelFixture()
-    : m_scheduler(m_io)
-  {
-  }
+  Scheduler scheduler(io);
 
-  void
-  cancelSelf()
-  {
-    m_scheduler.cancelEvent(m_selfEventId);
-  }
+  EventId selfEventId;
+  selfEventId = scheduler.scheduleEvent(time::milliseconds(100), [&] {
+      scheduler.cancelEvent(selfEventId);
+    });
 
-  boost::asio::io_service m_io;
-  Scheduler m_scheduler;
-  EventId m_selfEventId;
-};
-
-BOOST_FIXTURE_TEST_CASE(SelfCancel, SelfCancelFixture)
-{
-  m_selfEventId = m_scheduler.scheduleEvent(time::milliseconds(100),
-                                            bind(&SelfCancelFixture::cancelSelf, this));
-
-  BOOST_REQUIRE_NO_THROW(m_io.run());
+  BOOST_REQUIRE_NO_THROW(advanceClocks(time::milliseconds(100), 10));
 }
 
-struct SelfRescheduleFixture
+class SelfRescheduleFixture : public UnitTestTimeFixture
 {
+public:
   SelfRescheduleFixture()
-    : m_scheduler(m_io)
-    , m_count(0)
+    : scheduler(io)
+    , count(0)
   {
   }
 
   void
   reschedule()
   {
-    EventId eventId = m_scheduler.scheduleEvent(time::milliseconds(100),
-                                                bind(&SelfRescheduleFixture::reschedule, this));
-    m_scheduler.cancelEvent(m_selfEventId);
-    m_selfEventId = eventId;
+    EventId eventId = scheduler.scheduleEvent(time::milliseconds(100),
+                                              bind(&SelfRescheduleFixture::reschedule, this));
+    scheduler.cancelEvent(selfEventId);
+    selfEventId = eventId;
 
-    if(m_count < 5)
-      m_count++;
+    if (count < 5)
+      count++;
     else
-      m_scheduler.cancelEvent(m_selfEventId);
+      scheduler.cancelEvent(selfEventId);
   }
 
   void
   reschedule2()
   {
-    m_scheduler.cancelEvent(m_selfEventId);
+    scheduler.cancelEvent(selfEventId);
 
-
-    if(m_count < 5)
-      {
-        m_selfEventId = m_scheduler.scheduleEvent(time::milliseconds(100),
-                                                  bind(&SelfRescheduleFixture::reschedule2, this));
-        m_count++;
-      }
-  }
-
-  void
-  doNothing()
-  {
-    m_count++;
+    if (count < 5)  {
+      selfEventId = scheduler.scheduleEvent(time::milliseconds(100),
+                                            bind(&SelfRescheduleFixture::reschedule2, this));
+      count++;
+    }
   }
 
   void
   reschedule3()
   {
-    m_scheduler.cancelEvent(m_selfEventId);
+    scheduler.cancelEvent(selfEventId);
 
-    m_scheduler.scheduleEvent(time::milliseconds(100),
-                              bind(&SelfRescheduleFixture::doNothing, this));
-    m_scheduler.scheduleEvent(time::milliseconds(100),
-                              bind(&SelfRescheduleFixture::doNothing, this));
-    m_scheduler.scheduleEvent(time::milliseconds(100),
-                              bind(&SelfRescheduleFixture::doNothing, this));
-    m_scheduler.scheduleEvent(time::milliseconds(100),
-                              bind(&SelfRescheduleFixture::doNothing, this));
-    m_scheduler.scheduleEvent(time::milliseconds(100),
-                              bind(&SelfRescheduleFixture::doNothing, this));
-    m_scheduler.scheduleEvent(time::milliseconds(100),
-                              bind(&SelfRescheduleFixture::doNothing, this));
+    scheduler.scheduleEvent(time::milliseconds(100), [&] { ++count; });
+    scheduler.scheduleEvent(time::milliseconds(100), [&] { ++count; });
+    scheduler.scheduleEvent(time::milliseconds(100), [&] { ++count; });
+    scheduler.scheduleEvent(time::milliseconds(100), [&] { ++count; });
+    scheduler.scheduleEvent(time::milliseconds(100), [&] { ++count; });
+    scheduler.scheduleEvent(time::milliseconds(100), [&] { ++count; });
   }
 
-  boost::asio::io_service m_io;
-  Scheduler m_scheduler;
-  EventId m_selfEventId;
-  int m_count;
-
+  Scheduler scheduler;
+  EventId selfEventId;
+  size_t count;
 };
 
 BOOST_FIXTURE_TEST_CASE(Reschedule, SelfRescheduleFixture)
 {
-  m_selfEventId = m_scheduler.scheduleEvent(time::seconds(0),
-                                            bind(&SelfRescheduleFixture::reschedule, this));
+  selfEventId = scheduler.scheduleEvent(time::seconds(0),
+                                        bind(&SelfRescheduleFixture::reschedule, this));
 
-  BOOST_REQUIRE_NO_THROW(m_io.run());
+  BOOST_REQUIRE_NO_THROW(advanceClocks(time::milliseconds(10), 1000));
 
-  BOOST_CHECK_EQUAL(m_count, 5);
+  BOOST_CHECK_EQUAL(count, 5);
 }
 
 BOOST_FIXTURE_TEST_CASE(Reschedule2, SelfRescheduleFixture)
 {
-  m_selfEventId = m_scheduler.scheduleEvent(time::seconds(0),
-                                            bind(&SelfRescheduleFixture::reschedule2, this));
+  selfEventId = scheduler.scheduleEvent(time::seconds(0),
+                                        bind(&SelfRescheduleFixture::reschedule2, this));
 
-  BOOST_REQUIRE_NO_THROW(m_io.run());
+  BOOST_REQUIRE_NO_THROW(advanceClocks(time::milliseconds(10), 1000));
 
-  BOOST_CHECK_EQUAL(m_count, 5);
+  BOOST_CHECK_EQUAL(count, 5);
 }
 
 BOOST_FIXTURE_TEST_CASE(Reschedule3, SelfRescheduleFixture)
 {
-  m_selfEventId = m_scheduler.scheduleEvent(time::seconds(0),
-                                            bind(&SelfRescheduleFixture::reschedule3, this));
+  selfEventId = scheduler.scheduleEvent(time::seconds(0),
+                                        bind(&SelfRescheduleFixture::reschedule3, this));
 
-  BOOST_REQUIRE_NO_THROW(m_io.run());
+  BOOST_REQUIRE_NO_THROW(advanceClocks(time::milliseconds(10), 1000));
 
-  BOOST_CHECK_EQUAL(m_count, 6);
+  BOOST_CHECK_EQUAL(count, 6);
 }
 
 
-struct CancelAllFixture
+struct CancelAllFixture : public UnitTestTimeFixture
 {
   CancelAllFixture()
-    : m_scheduler(m_io)
-    , m_count(0)
+    : scheduler(io)
+    , count(0)
   {
   }
 
   void
-  cancelAll()
-  {
-    m_scheduler.cancelAllEvents();
-  }
-
-  void
   event()
   {
-    ++m_count;
+    ++count;
 
-    m_scheduler.scheduleEvent(time::seconds(1),
-                              bind(&CancelAllFixture::event, this));
+    scheduler.scheduleEvent(time::seconds(1), [&] { event(); });
   }
 
-  void
-  abort()
-  {
-    m_io.stop();
-  }
-
-  boost::asio::io_service m_io;
-  Scheduler m_scheduler;
-  uint32_t m_count;
+  Scheduler scheduler;
+  uint32_t count;
 };
 
 
 BOOST_FIXTURE_TEST_CASE(CancelAll, CancelAllFixture)
 {
-  m_scheduler.scheduleEvent(time::milliseconds(500),
-                            bind(&CancelAllFixture::cancelAll, this));
+  scheduler.scheduleEvent(time::milliseconds(500), [&] { scheduler.cancelAllEvents(); });
 
-  m_scheduler.scheduleEvent(time::seconds(1),
-                            bind(&CancelAllFixture::event, this));
+  scheduler.scheduleEvent(time::seconds(1), [&] { event(); });
 
-  m_scheduler.scheduleEvent(time::seconds(3),
-                            bind(&CancelAllFixture::abort, this));
+  scheduler.scheduleEvent(time::seconds(3), [] {
+      BOOST_ERROR("This event should have been cancelled" );
+    });
 
-  BOOST_REQUIRE_NO_THROW(m_io.run());
+  advanceClocks(time::milliseconds(100), 100);
 
-  BOOST_CHECK_EQUAL(m_count, 0);
+  BOOST_CHECK_EQUAL(count, 0);
 }
 
 
 BOOST_AUTO_TEST_SUITE_END()
 
+} // namespace tests
 } // namespace ndn