all: Refactoring work with time using boost::chrono

Now the library has two clocks: time::steady_clock and
time::system_clock, following (boost|std)::chrono.  In addition to
standard now() method, the library contains several helpers to convert
to/from UnixTimestamp (microsecond resolution) and IsoString (optional
microsecond resolution).  The IsoString conversions use
boost::posix_time routines, since boost::chrono supports extended IO
support only starting boost version 1.52 (Boost Chrono V2).

This commit breaks compatibility with previous API.  All time-related
Data/Interest calls must explicitly use time units to specify
FreshnessPeriod/InterestLifetime.

Brief usage/conversion guide:

- creation of time units does not support double/float types.  If
  necessary to create time unit from double, ``ndn::duration<double>`` (for
  seconds) needs to be used instead.  In some cases, this would also
  require ``ndn::duration_cast``, if the target is not ``ndn::nanoseconds``.
- ndn::getNow, ndn::ndn_getNowMilliseconds, ndn::time::now are all
  removed in favor of the now() method in a specific clock:

    * time::system_clock::now();
    * time::steady_clock::now();

- When necessary to convert system_clock::TimePoint to unix timestamp,
  ``time::toUnixTimestamp`` can be used.  This method return number of
  milliseconds since UNIX epoch as ``ndn::time::milliseconds`` type.
  Use count() method to obtain number as an integral value.

Change-Id: Icd688bc6766e008d60c3d2888173627874526e47
Refs: #1152
diff --git a/tests-integrated/test-faces.cpp b/tests-integrated/test-faces.cpp
new file mode 100644
index 0000000..03bfa9b
--- /dev/null
+++ b/tests-integrated/test-faces.cpp
@@ -0,0 +1,190 @@
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <boost/test/unit_test.hpp>
+#include "face.hpp"
+#include "util/scheduler.hpp"
+
+using namespace std;
+namespace ndn {
+
+BOOST_AUTO_TEST_SUITE(TestFaces)
+
+struct FacesFixture
+{
+  FacesFixture()
+    : dataCount(0)
+    , timeoutCount(0)
+    , regPrefixId(0)
+    , inInterestCount(0)
+    , inInterestCount2(0)
+    , regFailedCount(0)
+  {
+  }
+  
+  void
+  onData()
+  {
+    ++dataCount;
+  }
+
+  void
+  onTimeout()
+  {
+    ++timeoutCount;
+  }
+
+  void
+  onInterest(Face& face)
+  {
+    ++inInterestCount;
+
+    face.unsetInterestFilter(regPrefixId);
+  }
+
+  void
+  onInterest2(Face& face)
+  {
+    ++inInterestCount2;
+
+    face.unsetInterestFilter(regPrefixId2);
+  }
+
+  void
+  onRegFailed()
+  {
+    ++regFailedCount;
+  }
+
+  void
+  expressInterest(Face& face, const Name& name)
+  {
+    Interest i(name);
+    i.setInterestLifetime(time::milliseconds(50));
+    face.expressInterest(i,
+                         bind(&FacesFixture::onData, this),
+                         bind(&FacesFixture::onTimeout, this));
+  }
+
+  void
+  terminate(Face& face)
+  {
+    face.shutdown();
+  }
+
+  uint32_t dataCount;
+  uint32_t timeoutCount;
+
+  const RegisteredPrefixId* regPrefixId;
+  const RegisteredPrefixId* regPrefixId2;
+  uint32_t inInterestCount;
+  uint32_t inInterestCount2;
+  uint32_t regFailedCount;
+};
+
+BOOST_FIXTURE_TEST_CASE (Unix, FacesFixture)
+{
+  Face face;
+
+  face.expressInterest(Interest("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY", time::milliseconds(1000)),
+                       ptr_lib::bind(&FacesFixture::onData, this),
+                       ptr_lib::bind(&FacesFixture::onTimeout, this));
+
+  BOOST_REQUIRE_NO_THROW(face.processEvents());
+
+  BOOST_CHECK_EQUAL(dataCount, 1);
+  BOOST_CHECK_EQUAL(timeoutCount, 0);
+
+  face.expressInterest(Interest("/localhost/non-existing/data/should/not/exist/anywhere", time::milliseconds(50)),
+                       ptr_lib::bind(&FacesFixture::onData, this),
+                       ptr_lib::bind(&FacesFixture::onTimeout, this));
+  
+  BOOST_REQUIRE_NO_THROW(face.processEvents());
+
+  BOOST_CHECK_EQUAL(dataCount, 1);
+  BOOST_CHECK_EQUAL(timeoutCount, 1);
+}
+
+BOOST_FIXTURE_TEST_CASE (Tcp, FacesFixture)
+{
+  Face face("localhost");
+
+  face.expressInterest(Interest("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY", time::milliseconds(1000)),
+                       bind(&FacesFixture::onData, this),
+                       bind(&FacesFixture::onTimeout, this));
+
+  BOOST_REQUIRE_NO_THROW(face.processEvents());
+
+  BOOST_CHECK_EQUAL(dataCount, 1);
+  BOOST_CHECK_EQUAL(timeoutCount, 0);
+
+  face.expressInterest(Interest("/localhost/non-existing/data/should/not/exist/anywhere", time::milliseconds(50)),
+                       bind(&FacesFixture::onData, this),
+                       bind(&FacesFixture::onTimeout, this));
+
+  BOOST_REQUIRE_NO_THROW(face.processEvents());
+
+  BOOST_CHECK_EQUAL(dataCount, 1);
+  BOOST_CHECK_EQUAL(timeoutCount, 1);
+}
+
+
+BOOST_FIXTURE_TEST_CASE (SetFilter, FacesFixture)
+{
+  Face face;
+  Face face2(face.ioService());
+  Scheduler scheduler(*face.ioService());
+  scheduler.scheduleEvent(time::milliseconds(300),
+                          bind(&FacesFixture::terminate, this, func_lib::ref(face)));
+  
+  regPrefixId = face.setInterestFilter("/Hello/World",
+                                       bind(&FacesFixture::onInterest, this, func_lib::ref(face)),
+                                       bind(&FacesFixture::onRegFailed, this));
+
+  scheduler.scheduleEvent(time::milliseconds(200),
+                          bind(&FacesFixture::expressInterest, this,
+                               func_lib::ref(face2), Name("/Hello/World/!")));
+  
+  BOOST_REQUIRE_NO_THROW(face.processEvents());
+
+  BOOST_CHECK_EQUAL(regFailedCount, 0);  
+  BOOST_CHECK_EQUAL(inInterestCount, 1);  
+  BOOST_CHECK_EQUAL(timeoutCount, 1);
+  BOOST_CHECK_EQUAL(dataCount, 0);
+}
+
+BOOST_FIXTURE_TEST_CASE (SetTwoFilters, FacesFixture)
+{
+  Face face;
+  Face face2(face.ioService());
+  Scheduler scheduler(*face.ioService());
+  scheduler.scheduleEvent(time::seconds(1),
+                          bind(&FacesFixture::terminate, this, func_lib::ref(face)));
+  
+  regPrefixId = face.setInterestFilter("/Hello/World",
+                                       bind(&FacesFixture::onInterest, this, func_lib::ref(face)),
+                                       bind(&FacesFixture::onRegFailed, this));
+  
+  regPrefixId2 = face.setInterestFilter("/Los/Angeles/Lakers",
+                                       bind(&FacesFixture::onInterest2, this, func_lib::ref(face)),
+                                       bind(&FacesFixture::onRegFailed, this));
+
+
+  scheduler.scheduleEvent(time::milliseconds(200),
+                          bind(&FacesFixture::expressInterest, this,
+                               func_lib::ref(face2), Name("/Hello/World/!")));
+  
+  BOOST_REQUIRE_NO_THROW(face.processEvents());
+
+  BOOST_CHECK_EQUAL(regFailedCount, 0);  
+  BOOST_CHECK_EQUAL(inInterestCount, 1);  
+  BOOST_CHECK_EQUAL(inInterestCount2, 0);  
+  BOOST_CHECK_EQUAL(timeoutCount, 1);
+  BOOST_CHECK_EQUAL(dataCount, 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace ndn