build: Fixing build and unit tests

Use only C++ and boost methods (memory copying, comparison, time
operations), which are guaranteed to be present on all platforms
with C++ and boost libraries.

Change-Id: Ia2883555c55909a4f7a877cf6d5fbd49b12c73c8
diff --git a/.travis.yml b/.travis.yml
index 3199dc8..b187ec4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,7 +14,7 @@
   - travis_retry sudo apt-get install -qq libsqlite3-dev
 script:
   - ./waf configure --with-tests
-  - ./waf
+  - ./waf -j1
   - sudo ./waf install
   - sudo ldconfig
   - #
diff --git a/examples/wscript b/examples/wscript
index a3a5e8a..2cf856f 100644
--- a/examples/wscript
+++ b/examples/wscript
@@ -7,6 +7,6 @@
         bld(features=['cxx', 'cxxprogram'],
             target = '%s' % (str(app.change_ext('','.cpp'))),
             source = app,
-            use = 'ndn-cpp-dev-stlib',
+            use = 'ndn-cpp-dev',
             install_prefix = None,
             )        
diff --git a/src/common.cpp b/src/common.cpp
index 31569e3..53df6e1 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -7,13 +7,7 @@
 
 #include <sstream>
 #include <ndn-cpp-dev/common.hpp>
-
-#if NDN_CPP_HAVE_TIME_H
-#include <time.h>
-#endif
-#if NDN_CPP_HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
+#include "util/time.hpp"
 
 using namespace std;
 
@@ -40,10 +34,7 @@
 MillisecondsSince1970
 getNow()
 {
-  struct timeval t;
-  // Note: configure.ac requires gettimeofday.
-  gettimeofday(&t, 0);
-  return t.tv_sec * 1000.0 + t.tv_usec / 1000.0;
+  return getNowMilliseconds();
 }
 
 
diff --git a/src/encoding/cryptopp/asn_ext.cpp b/src/encoding/cryptopp/asn_ext.cpp
index 7a8eda1..4df06c5 100644
--- a/src/encoding/cryptopp/asn_ext.cpp
+++ b/src/encoding/cryptopp/asn_ext.cpp
@@ -8,14 +8,6 @@
 
 #include <ndn-cpp-dev/ndn-cpp-config.h>
 #include "asn_ext.hpp"
-
-#if NDN_CPP_HAVE_TIME_H
-#include <time.h>
-#endif
-#if NDN_CPP_HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
 #include "../../util/time.hpp"
 
 #include <boost/format.hpp>
@@ -33,17 +25,21 @@
   else if (time > 2e14)
     // 2e14 is about the year 8300.  We don't want to go over a 4-digit year.
     throw Asn::Error("Calendar time value out of range");
-  
-  time_t secondsSince1970 = time / 1000;
-  struct tm* gmt = gmtime(&secondsSince1970);
 
-  std::string asn1time ((boost::format("%04d%02d%02d%02d%02d%02dZ")
-                         % (1900 + gmt->tm_year)
-                         % (gmt->tm_mon + 1)
-                         % gmt->tm_mday
-                         % gmt->tm_hour
-                         % gmt->tm_min
-                         % gmt->tm_sec).str());
+
+  boost::posix_time::ptime boostTime =
+    UNIX_EPOCH_TIME + boost::posix_time::milliseconds(time);
+  
+  const boost::format f = boost::format("%04d%02d%02d%02d%02d%02dZ")
+                % boostTime.date().year_month_day().year
+                % boostTime.date().year_month_day().month.as_number()
+                % boostTime.date().year_month_day().day.as_number()
+                % boostTime.time_of_day().hours()
+                % boostTime.time_of_day().minutes()
+                % boostTime.time_of_day().seconds()
+    ;
+
+  std::string asn1time = f.str();
   
   bt.Put(GENERALIZED_TIME);
   size_t lengthBytes = DERLengthEncode(bt, asn1time.size());
diff --git a/src/name.cpp b/src/name.cpp
index 3e2d1fe..484fdc0 100644
--- a/src/name.cpp
+++ b/src/name.cpp
@@ -8,7 +8,7 @@
 
 #include <stdexcept>
 #include <algorithm>
-#include <string.h>
+#include <cstring>
 #include <ndn-cpp-dev/name.hpp>
 #include "util/time.hpp"
 
@@ -90,7 +90,7 @@
     return 1;
 
   // The components are equal length.  Just do a byte compare.  
-  return memcmp(getValue().buf(), other.getValue().buf(), getValue().size());
+  return std::memcmp(getValue().buf(), other.getValue().buf(), getValue().size());
 }
 
 // const Block &
diff --git a/src/util/logging.hpp b/src/util/logging.hpp
index 73c6d12..e9bf4d5 100644
--- a/src/util/logging.hpp
+++ b/src/util/logging.hpp
@@ -64,11 +64,10 @@
 
 #ifdef _DEBUG
 
-#include <sys/time.h>
 #include <iostream>
 
 #define _LOG_DEBUG(x) \
-  { time_t now = time(0); std::string s = std::string(ctime(&now)); std::clog << s.substr(0, s.size() - 1) << " " << x << std::endl; }
+  { std::clog << s.substr(0, s.size() - 1) << " " << x << std::endl; }
 
 #else
 #define _LOG_DEBUG(x)
diff --git a/src/util/time.cpp b/src/util/time.cpp
deleted file mode 100644
index 03eb81b..0000000
--- a/src/util/time.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- * Copyright (C) 2013 Regents of the University of California.
- * @author: Jeff Thompson <jefft0@remap.ucla.edu>
- * See COPYING for copyright and distribution information.
- */
-
-#include <ndn-cpp-dev/ndn-cpp-config.h>
-#if NDN_CPP_HAVE_TIME_H
-#include <time.h>
-#endif
-#if NDN_CPP_HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-#include <math.h>
-#include <string.h>
-#include <stdio.h>
-#include "time.hpp"
-
-namespace ndn {
-
-MillisecondsSince1970 
-ndn_getNowMilliseconds()
-{
-  struct timeval t;
-  // Note: configure.ac requires gettimeofday.
-  gettimeofday(&t, 0);
-  return t.tv_sec * 1000.0 + t.tv_usec / 1000.0;
-}
-
-int
-ndn_toIsoString(MillisecondsSince1970 milliseconds, char *isoString)
-{
-#if NDN_CPP_HAVE_GMTIME_SUPPORT
-  if (milliseconds < 0)
-    return -1;
-  else if (milliseconds > 2e14)
-    // 2e14 is about the year 8300.  We don't want to go over a 4-digit year.
-    return -1;
-  
-  double secondsSince1970 = milliseconds / 1000.0;
-  char fractionBuffer[10];
-  sprintf(fractionBuffer, "%.06lf", fmod(secondsSince1970, 1.0));
-  const char *fraction = strchr(fractionBuffer, '.');
-  if (!fraction)
-    // Don't expect this to happen.
-    fraction = ".000000";
-    
-  time_t seconds = (time_t)secondsSince1970;
-  struct tm* gmt = gmtime(&seconds);
-  sprintf(isoString, "%04d%02d%02dT%02d%02d%02d%s", 1900 + gmt->tm_year, gmt->tm_mon + 1, gmt->tm_mday,
-    gmt->tm_hour, gmt->tm_min, gmt->tm_sec, fraction);
-  
-  return 0;
-#else
-  return -1;
-#endif
-}
-
-int
-ndn_fromIsoString(const char* isoString, MillisecondsSince1970 *milliseconds)
-{
-#if NDN_CPP_HAVE_GMTIME_SUPPORT
-  // Initialize time zone, etc.
-  time_t dummyTime = 0;
-  struct tm tm1 = *gmtime(&dummyTime);
-  
-  sscanf(isoString, "%4d%2d%2dT%2d%2d", &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour, &tm1.tm_min);
-  // Skip the time past minutes and get the float seconds.
-  double seconds;
-  sscanf(isoString + (4 + 2 + 2 + 1 + 2 + 2), "%lf", &seconds);
-  
-  // tm_year starts from 1900.
-  tm1.tm_year -= 1900;
-  // tm_mon starts from 0, not 1.
-  tm1.tm_mon -= 1;
-  tm1.tm_sec = 0;
-  
-  *milliseconds = (timegm(&tm1) + seconds) * 1000.0;
-  return 0;
-#else
-  return -1;
-#endif
-}
-
-} // namespace ndn
diff --git a/src/util/time.hpp b/src/util/time.hpp
index 5e5dc7c..7b42b4a 100644
--- a/src/util/time.hpp
+++ b/src/util/time.hpp
@@ -9,17 +9,28 @@
 #define NDN_TIME_HPP
 
 #include "ndn-cpp-dev/common.hpp"
+#include <boost/date_time/posix_time/posix_time.hpp>
 
 namespace ndn {
 
-MillisecondsSince1970 
-ndn_getNowMilliseconds();
+const boost::posix_time::ptime UNIX_EPOCH_TIME =
+  boost::posix_time::ptime (boost::gregorian::date (1970, boost::gregorian::Jan, 1));
 
-int
-ndn_toIsoString(MillisecondsSince1970 milliseconds, char *isoString);
+/**
+ * @brief Get the current time in milliseconds since 1/1/1970, including fractions of a millisecond
+ */
+inline MillisecondsSince1970 
+getNowMilliseconds()
+{
+  return (boost::posix_time::microsec_clock::universal_time() - UNIX_EPOCH_TIME).total_milliseconds();
+}
 
-int
-ndn_fromIsoString(const char* isoString, MillisecondsSince1970 *milliseconds);
+inline MillisecondsSince1970 
+ndn_getNowMilliseconds()
+{
+  return getNowMilliseconds();
+}
+
 
 /**
  * Convert to the ISO string representation of the time.
@@ -29,12 +40,13 @@
 inline std::string
 toIsoString(const MillisecondsSince1970& time)
 {
-  char isoString[25];
-  int error;
-  if ((error = ndn_toIsoString(time, isoString)))
-    throw std::runtime_error("toIsoString");
-  
-  return isoString;
+  boost::posix_time::ptime boostTime = UNIX_EPOCH_TIME + boost::posix_time::milliseconds(time);
+
+  /// @todo Determine whether this is necessary at all
+  if ((time % 1000) == 0)
+    return boost::posix_time::to_iso_string(boostTime) + ".000000"; 
+  else
+    return boost::posix_time::to_iso_string(boostTime);
 }
   
 /**
@@ -45,12 +57,9 @@
 inline MillisecondsSince1970
 fromIsoString(const std::string& isoString)
 {
-  MillisecondsSince1970 milliseconds;
-  int error;
-  if ((error = ndn_fromIsoString(isoString.c_str(), &milliseconds)))
-    throw std::runtime_error("fromIsoString");
+  boost::posix_time::ptime boostTime = boost::posix_time::from_iso_string(isoString);
   
-  return milliseconds;
+  return (boostTime-UNIX_EPOCH_TIME).total_milliseconds();
 }
 
 } // namespace ndn
diff --git a/tests/test-encode-decode-certificate.cpp b/tests/test-encode-decode-certificate.cpp
index b8f0159..8da32bb 100644
--- a/tests/test-encode-decode-certificate.cpp
+++ b/tests/test-encode-decode-certificate.cpp
@@ -1,6 +1,5 @@
 /**
  * Copyright (C) 2013 Regents of the University of California.
- * @author: Jeff Thompson <jefft0@remap.ucla.edu>
  * See COPYING for copyright and distribution information.
  */
 
diff --git a/tests/test-sec-tpm-file.cpp b/tests/test-sec-tpm-file.cpp
index 9d75a38..a74a84b 100644
--- a/tests/test-sec-tpm-file.cpp
+++ b/tests/test-sec-tpm-file.cpp
@@ -32,10 +32,12 @@
   SecTpmFile tpm;
 
   Name keyName("/tmp/ksk-123456");
-  tpm.generateKeyPairInTpm(keyName, KEY_TYPE_RSA, 2048);
+  try {
+    tpm.generateKeyPairInTpm(keyName, KEY_TYPE_RSA, 2048);
+  }
+  catch(const SecTpm::Error&) {
+  }
   
-
-
   Data data("/tmp/test/1");
   const uint8_t content[] = {0x01, 0x02, 0x03, 0x04};
 
diff --git a/tests/test-time.cpp b/tests/test-time.cpp
new file mode 100644
index 0000000..bc77fbd
--- /dev/null
+++ b/tests/test-time.cpp
@@ -0,0 +1,23 @@
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#include <boost/test/unit_test.hpp>
+
+#include <../src/util/time.hpp>
+
+BOOST_AUTO_TEST_SUITE(TestTime)
+
+BOOST_AUTO_TEST_CASE (Simple)
+{
+  ndn::MillisecondsSince1970 value = ndn::getNowMilliseconds();
+  BOOST_CHECK_GT(value, 1390966967032);
+
+  BOOST_CHECK_EQUAL(ndn::toIsoString(1390966967032), "20140129T034247.032000");
+  BOOST_CHECK_EQUAL(ndn::fromIsoString("20140129T034247.032000"), 1390966967032);
+
+  BOOST_CHECK_EQUAL(ndn::fromIsoString("20140129T034247.032000Z"), 1390966967032);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/wscript b/tests/wscript
index 73f722a..c63c031 100644
--- a/tests/wscript
+++ b/tests/wscript
@@ -7,6 +7,6 @@
         target="unit-tests",
         features = "cxx cxxprogram",
         source = bld.path.ant_glob(['**/*.cpp']),
-        use = 'lib-objects',
+        use = 'ndn-cpp-dev',
         install_prefix = None,
         )
diff --git a/tools/wscript b/tools/wscript
index f0114cf..be76916 100644
--- a/tools/wscript
+++ b/tools/wscript
@@ -7,5 +7,5 @@
         bld(features=['cxx', 'cxxprogram'],
             target = '%s' % (str(app.change_ext('','.cpp'))),
             source = app,
-            use = 'ndn-cpp-dev-stlib',
+            use = 'ndn-cpp-dev',
             )        
diff --git a/wscript b/wscript
index 979324d..f71a747 100644
--- a/wscript
+++ b/wscript
@@ -33,20 +33,6 @@
     if conf.options.with_tests:
         conf.env['WITH_TESTS'] = True
 
-    # Optional functions
-    for func in ['memcmp', 'memcpy', 'memset']:
-        conf.check(function_name=func, header_name='string.h', mandatory=False)
-
-    # Mandatory functions
-    for func in ['strchr', 'sscanf']:
-        conf.check(function_name=func, header_name=['string.h', 'stdio.h'])
-
-    # Mandatory headers
-    for header in ['time.h', 'sys/time.h']:
-        conf.check(header_name=header)
-
-    conf.check(function_name='gettimeofday', header_name=['time.h', 'sys/time.h'])
-
     conf.check_openssl()
 
     if conf.options.debug:
@@ -100,7 +86,7 @@
         conf.define('HAVE_CXX11', 1)
     else:
         if conf.options.use_system_boost:
-            USED_BOOST_LIBS = 'system filesystem iostreams'
+            USED_BOOST_LIBS = 'system filesystem date_time iostreams'
             if conf.env['WITH_TESTS']:
                 USED_BOOST_LIBS += " unit_test_framework"
 
@@ -115,33 +101,26 @@
 
 def build (bld):
     libndn_cpp = bld (
-        target="lib-objects",
-        name = "lib-objects",
-        features=['cxx'],
-        source = bld.path.ant_glob(['src/**/*.cpp',
-                                    'new/**/*.cpp']),
+        features=['cxx', 'cxxshlib', 'cxxstlib'],
+        vnum = "0.3.0",
+        target="ndn-cpp-dev",
+        name = "ndn-cpp-dev",
+        source = bld.path.ant_glob('src/**/*.cpp',
+                                   excl = ['src/**/*-osx.cpp', 'src/**/*-sqlite3.cpp']),
         use = 'BOOST OPENSSL LOG4CXX CRYPTOPP SQLITE3',
         includes = "include",
         export_includes = "include",
         )
 
     if Utils.unversioned_sys_platform () == "darwin":
+        libndn_cpp.source += bld.path.ant_glob('src/**/*-osx.cpp')
         libndn_cpp.mac_app = True
         libndn_cpp.use += " OSX_COREFOUNDATION OSX_SECURITY"
 
-    shlib = bld(features = 'cxx cxxshlib',
-                vnum = "0.3.0",
-                target = "ndn-cpp-dev",
-                use = "lib-objects",
-                name = "ndn-cpp-dev-shlib",
-                )
+    # In case we want to make it optional later
+    libndn_cpp.source += bld.path.ant_glob('src/**/*-sqlite3.cpp')
 
-    stlib = bld(features = 'cxx cxxstlib',
-                target = "ndn-cpp-dev",
-                use = "lib-objects",
-                name = "ndn-cpp-dev-stlib",
-                )
-        
+
     pkgconfig_libs = []
     pkgconfig_ldflags = []
     pkgconfig_includes = []
@@ -178,9 +157,9 @@
       
     headers = bld.path.ant_glob(['src/**/*.hpp',
                                  'src/**/*.h'])
-    bld.install_files("%s/ndn-cpp" % bld.env['INCLUDEDIR'], headers, relative_trick=True, cwd=bld.path.find_node('src'))
+    bld.install_files("%s/ndn-cpp-dev" % bld.env['INCLUDEDIR'], headers, relative_trick=True, cwd=bld.path.find_node('src'))
 
-    bld.install_files("%s/ndn-cpp" % bld.env['INCLUDEDIR'], bld.path.find_resource('include/ndn-cpp/ndn-cpp-config.h'))
+    bld.install_files("%s/ndn-cpp-dev" % bld.env['INCLUDEDIR'], bld.path.find_resource('include/ndn-cpp-dev/ndn-cpp-config.h'))
 
     headers = bld.path.ant_glob(['include/**/*.hpp', 'include/**/*.h'])
     bld.install_files("%s" % bld.env['INCLUDEDIR'], headers, relative_trick=True, cwd=bld.path.find_node('include'))