util: FaceUri: modernize and simplify code with C++11 features

Change-Id: Ie6a59567a635b6c69b970e9e1e50eafff14ea7fa
diff --git a/src/util/face-uri.cpp b/src/util/face-uri.cpp
index f38e8c2..c09da8a 100644
--- a/src/util/face-uri.cpp
+++ b/src/util/face-uri.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2015-2016, Regents of the University of California,
+ * Copyright (c) 2014-2016, Regents of the University of California,
  *                          Arizona Board of Regents,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University,
@@ -27,13 +27,14 @@
 
 #include "face-uri.hpp"
 #include "dns.hpp"
+#include "ethernet.hpp"
 
-#include <set>
 #include <boost/concept_check.hpp>
-#include <boost/regex.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/mpl/vector.hpp>
 #include <boost/mpl/for_each.hpp>
+#include <boost/regex.hpp>
+#include <set>
 
 namespace ndn {
 namespace util {
@@ -53,10 +54,8 @@
 }
 
 FaceUri::FaceUri(const char* uri)
+  : FaceUri(std::string(uri))
 {
-  if (!parse(uri)) {
-    BOOST_THROW_EXCEPTION(Error("Malformed URI: " + std::string(uri)));
-  }
 }
 
 bool
@@ -64,9 +63,9 @@
 {
   m_scheme.clear();
   m_host.clear();
-  m_isV6 = false;
   m_port.clear();
   m_path.clear();
+  m_isV6 = false;
 
   static const boost::regex protocolExp("(\\w+\\d?(\\+\\w+)?)://([^/]*)(\\/[^?]*)?");
   boost::smatch protocolMatch;
@@ -124,19 +123,19 @@
 }
 
 FaceUri::FaceUri(const boost::asio::ip::tcp::endpoint& endpoint, const std::string& scheme)
-  : m_scheme(scheme)
 {
   m_isV6 = endpoint.address().is_v6();
+  m_scheme = scheme;
   m_host = endpoint.address().to_string();
   m_port = to_string(endpoint.port());
 }
 
 #ifdef BOOST_ASIO_HAS_LOCAL_SOCKETS
 FaceUri::FaceUri(const boost::asio::local::stream_protocol::endpoint& endpoint)
-  : m_isV6(false)
+  : m_scheme("unix")
+  , m_path(endpoint.path())
+  , m_isV6(false)
 {
-  m_scheme = "unix";
-  m_path = endpoint.path();
 }
 #endif // BOOST_ASIO_HAS_LOCAL_SOCKETS
 
@@ -150,10 +149,10 @@
 }
 
 FaceUri::FaceUri(const ethernet::Address& address)
-  : m_isV6(true)
+  : m_scheme("ether")
+  , m_host(address.toString())
+  , m_isV6(true)
 {
-  m_scheme = "ether";
-  m_host = address.toString();
 }
 
 FaceUri
@@ -178,11 +177,11 @@
 bool
 FaceUri::operator==(const FaceUri& rhs) const
 {
-  return (m_scheme == rhs.m_scheme &&
-          m_host == rhs.m_host &&
-          m_isV6 == rhs.m_isV6 &&
-          m_port == rhs.m_port &&
-          m_path == rhs.m_path);
+  return m_isV6 == rhs.m_isV6 &&
+         m_scheme == rhs.m_scheme &&
+         m_host == rhs.m_host &&
+         m_port == rhs.m_port &&
+         m_path == rhs.m_path;
 }
 
 bool
@@ -216,6 +215,7 @@
   return os;
 }
 
+
 /** \brief a CanonizeProvider provides FaceUri canonization functionality for a group of schemes
  */
 class CanonizeProvider : noncopyable
@@ -244,11 +244,7 @@
   std::set<std::string>
   getSchemes() const override
   {
-    std::set<std::string> schemes;
-    schemes.insert(m_baseScheme);
-    schemes.insert(m_v4Scheme);
-    schemes.insert(m_v6Scheme);
-    return schemes;
+    return {m_baseScheme, m_v4Scheme, m_v6Scheme};
   }
 
   bool
@@ -272,8 +268,8 @@
     else {
       return false;
     }
-    return !static_cast<bool>(ec) && addr.to_string() == faceUri.getHost() &&
-           this->checkAddress(addr).first;
+
+    return !ec && addr.to_string() == faceUri.getHost() && checkAddress(addr).first;
   }
 
   void
@@ -300,7 +296,7 @@
     }
 
     // make a copy because caller may modify faceUri
-    shared_ptr<FaceUri> uri = make_shared<FaceUri>(faceUri);
+    auto uri = make_shared<FaceUri>(faceUri);
     dns::asyncResolve(faceUri.getHost(),
       bind(&IpHostCanonizeProvider<Protocol>::onDnsSuccess, this, uri, onSuccess, onFailure, _1),
       bind(&IpHostCanonizeProvider<Protocol>::onDnsFailure, this, uri, onFailure, _1),
@@ -313,25 +309,25 @@
                          uint16_t defaultUnicastPort = 6363,
                          uint16_t defaultMulticastPort = 56363)
     : m_baseScheme(baseScheme)
-    , m_v4Scheme(baseScheme + "4")
-    , m_v6Scheme(baseScheme + "6")
+    , m_v4Scheme(baseScheme + '4')
+    , m_v6Scheme(baseScheme + '6')
     , m_defaultUnicastPort(defaultUnicastPort)
     , m_defaultMulticastPort(defaultMulticastPort)
   {
   }
 
 private:
-  // faceUri is a shared_ptr passed by value because this function can take ownership
   void
-  onDnsSuccess(shared_ptr<FaceUri> faceUri,
+  onDnsSuccess(const shared_ptr<FaceUri>& faceUri,
                const FaceUri::CanonizeSuccessCallback& onSuccess,
                const FaceUri::CanonizeFailureCallback& onFailure,
                const dns::IpAddress& ipAddress) const
   {
-    std::pair<bool, std::string> checkAddressRes = this->checkAddress(ipAddress);
-    if (!checkAddressRes.first) {
-      onFailure(checkAddressRes.second);
-      return;
+    bool isOk = false;
+    std::string reason;
+    std::tie(isOk, reason) = this->checkAddress(ipAddress);
+    if (!isOk) {
+      return onFailure(reason);
     }
 
     uint16_t port = 0;
@@ -343,8 +339,7 @@
         port = boost::lexical_cast<uint16_t>(faceUri->getPort());
       }
       catch (const boost::bad_lexical_cast&) {
-        onFailure("invalid port number");
-        return;
+        return onFailure("invalid port number '" + faceUri->getPort() + "'");
       }
     }
 
@@ -353,9 +348,9 @@
     onSuccess(canonicalUri);
   }
 
-  // faceUri is a shared_ptr passed by value because this function can take ownership
   void
-  onDnsFailure(shared_ptr<FaceUri> faceUri, const FaceUri::CanonizeFailureCallback& onFailure,
+  onDnsFailure(const shared_ptr<FaceUri>& faceUri,
+               const FaceUri::CanonizeFailureCallback& onFailure,
                const std::string& reason) const
   {
     onFailure(reason);
@@ -418,9 +413,7 @@
   std::set<std::string>
   getSchemes() const override
   {
-    std::set<std::string> schemes;
-    schemes.insert("ether");
-    return schemes;
+    return {"ether"};
   }
 
   bool
@@ -433,7 +426,7 @@
       return false;
     }
 
-    ethernet::Address addr = ethernet::Address::fromString(faceUri.getHost());
+    auto addr = ethernet::Address::fromString(faceUri.getHost());
     return addr.toString() == faceUri.getHost();
   }
 
@@ -443,10 +436,9 @@
            const FaceUri::CanonizeFailureCallback& onFailure,
            boost::asio::io_service& io, const time::nanoseconds& timeout) const override
   {
-    ethernet::Address addr = ethernet::Address::fromString(faceUri.getHost());
+    auto addr = ethernet::Address::fromString(faceUri.getHost());
     if (addr.isNull()) {
-      onFailure("cannot parse address");
-      return;
+      return onFailure("invalid ethernet address '" + faceUri.getHost() + "'");
     }
 
     FaceUri canonicalUri(addr);
@@ -491,13 +483,11 @@
   }
 };
 
-typedef boost::mpl::vector<
-    UdpCanonizeProvider*,
-    TcpCanonizeProvider*,
-    EtherCanonizeProvider*,
-    UdpDevCanonizeProvider*
-  > CanonizeProviders;
-typedef std::map<std::string, shared_ptr<CanonizeProvider> > CanonizeProviderTable;
+using CanonizeProviders = boost::mpl::vector<UdpCanonizeProvider*,
+                                             TcpCanonizeProvider*,
+                                             EtherCanonizeProvider*,
+                                             UdpDevCanonizeProvider*>;
+using CanonizeProviderTable = std::map<std::string, shared_ptr<CanonizeProvider>>;
 
 class CanonizeProviderTableInitializer
 {
@@ -508,17 +498,17 @@
   {
   }
 
-  template<typename CP> void
+  template<typename CP>
+  void
   operator()(CP*)
   {
     shared_ptr<CanonizeProvider> cp = make_shared<CP>();
-
-    std::set<std::string> schemes = cp->getSchemes();
+    auto schemes = cp->getSchemes();
     BOOST_ASSERT(!schemes.empty());
-    for (std::set<std::string>::iterator it = schemes.begin();
-         it != schemes.end(); ++it) {
-      BOOST_ASSERT(m_providerTable.count(*it) == 0);
-      m_providerTable[*it] = cp;
+
+    for (const auto& scheme : schemes) {
+      BOOST_ASSERT(m_providerTable.count(scheme) == 0);
+      m_providerTable[scheme] = cp;
     }
   }
 
@@ -536,23 +526,21 @@
   }
 
   auto it = providerTable.find(scheme);
-  if (it == providerTable.end()) {
-    return nullptr;
-  }
-  return it->second.get();
+  return it == providerTable.end() ? nullptr : it->second.get();
 }
 
+
 bool
 FaceUri::canCanonize(const std::string& scheme)
 {
-  return getCanonizeProvider(scheme) != 0;
+  return getCanonizeProvider(scheme) != nullptr;
 }
 
 bool
 FaceUri::isCanonical() const
 {
   const CanonizeProvider* cp = getCanonizeProvider(this->getScheme());
-  if (cp == 0) {
+  if (cp == nullptr) {
     return false;
   }
 
@@ -574,7 +562,6 @@
 
   static CanonizeSuccessCallback successNop = bind([]{});
   static CanonizeFailureCallback failureNop = bind([]{});
-
   cp->canonize(*this,
                onSuccess ? onSuccess : successNop,
                onFailure ? onFailure : failureNop,
diff --git a/src/util/face-uri.hpp b/src/util/face-uri.hpp
index b222323..f726388 100644
--- a/src/util/face-uri.hpp
+++ b/src/util/face-uri.hpp
@@ -1,12 +1,12 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  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
+ * Copyright (c) 2014-2016, 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).
  *
@@ -29,15 +29,19 @@
 #define NDN_UTIL_FACE_URI_HPP
 
 #include "../common.hpp"
-#include <boost/asio/ip/udp.hpp>
-#include <boost/asio/ip/tcp.hpp>
-#include <boost/asio/local/stream_protocol.hpp>
-#include "ethernet.hpp"
 #include "time.hpp"
 
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
+
 namespace ndn {
 namespace util {
 
+namespace ethernet {
+class Address;
+} // namespace ethernet
+
 /** \brief represents the underlying protocol and address used by a Face
  *  \sa http://redmine.named-data.net/projects/nfd/wiki/FaceMgmt#FaceUri
  */
@@ -82,7 +86,7 @@
   explicit
   FaceUri(const boost::asio::ip::tcp::endpoint& endpoint);
 
-  /// construct tcp canonical FaceUri with customized scheme
+  /// construct tcp canonical FaceUri with custom scheme
   FaceUri(const boost::asio::ip::tcp::endpoint& endpoint, const std::string& scheme);
 
 #ifdef BOOST_ASIO_HAS_LOCAL_SOCKETS
@@ -176,15 +180,16 @@
   void
   canonize(const CanonizeSuccessCallback& onSuccess,
            const CanonizeFailureCallback& onFailure,
-           boost::asio::io_service& io, const time::nanoseconds& timeout) const;
+           boost::asio::io_service& io,
+           const time::nanoseconds& timeout) const;
 
 private:
   std::string m_scheme;
   std::string m_host;
-  /// whether to add [] around host when writing string
-  bool m_isV6;
   std::string m_port;
   std::string m_path;
+  /// whether to add [] around host when writing string
+  bool m_isV6;
 
   friend std::ostream& operator<<(std::ostream& os, const FaceUri& uri);
 };
diff --git a/tests/unit-tests/util/face-uri.t.cpp b/tests/unit-tests/util/face-uri.t.cpp
index b63c2de..74c6784 100644
--- a/tests/unit-tests/util/face-uri.t.cpp
+++ b/tests/unit-tests/util/face-uri.t.cpp
@@ -1,12 +1,12 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2013-2016 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.
+ * Copyright (c) 2014-2016, 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).
  *
@@ -26,6 +26,7 @@
  */
 
 #include "util/face-uri.hpp"
+#include "util/ethernet.hpp"
 
 #include "boost-test.hpp"
 #include "../network-configuration-detector.hpp"
@@ -42,13 +43,17 @@
 class CanonizeFixture : noncopyable
 {
 protected:
-  CanonizeFixture()
-    : m_nPending(0)
-  {
-  }
-
   void
-  addTest(const std::string& request, bool shouldSucceed, const std::string& expectedUri);
+  addTest(const std::string& request, bool shouldSucceed, const std::string& expectedUri)
+  {
+    ++m_nPending;
+    auto tc = make_shared<CanonizeTestCase>(request, shouldSucceed, expectedUri);
+
+    FaceUri uri(request);
+    uri.canonize(bind(&CanonizeFixture::onCanonizeSuccess, this, tc, _1),
+                 bind(&CanonizeFixture::onCanonizeFailure, this, tc, _1),
+                 m_io, time::seconds(10));
+  }
 
   void
   runTests()
@@ -61,39 +66,38 @@
   class CanonizeTestCase
   {
   public:
-    CanonizeTestCase(const std::string& request,
-                     bool shouldSucceed, const std::string& expectedUri)
-      : m_shouldSucceed(shouldSucceed)
-      , m_expectedUri(expectedUri)
+    CanonizeTestCase(const std::string& request, bool shouldSucceed, const std::string& expectedUri)
+      : m_expectedUri(expectedUri)
       , m_message(request + " should " + (shouldSucceed ? "succeed" : "fail"))
+      , m_shouldSucceed(shouldSucceed)
       , m_isCompleted(false)
     {
     }
 
   public:
-    bool m_shouldSucceed;
     std::string m_expectedUri;
     std::string m_message;
+    bool m_shouldSucceed;
     bool m_isCompleted;
   };
 
-  // tc is a shared_ptr passed by value, because this function can take ownership
   void
-  onCanonizeSuccess(shared_ptr<CanonizeTestCase> tc, const FaceUri& canonicalUri)
+  onCanonizeSuccess(const shared_ptr<CanonizeTestCase>& tc, const FaceUri& canonicalUri)
   {
-    BOOST_CHECK(!tc->m_isCompleted);
+    BOOST_CHECK_EQUAL(tc->m_isCompleted, false);
     tc->m_isCompleted = true;
     --m_nPending;
 
     BOOST_CHECK_MESSAGE(tc->m_shouldSucceed, tc->m_message);
-    BOOST_CHECK_EQUAL(tc->m_expectedUri, canonicalUri.toString());
+    if (tc->m_shouldSucceed) {
+      BOOST_CHECK_EQUAL(canonicalUri.toString(), tc->m_expectedUri);
+    }
   }
 
-  // tc is a shared_ptr passed by value, because this function can take ownership
   void
-  onCanonizeFailure(shared_ptr<CanonizeTestCase> tc, const std::string& reason)
+  onCanonizeFailure(const shared_ptr<CanonizeTestCase>& tc, const std::string& reason)
   {
-    BOOST_CHECK(!tc->m_isCompleted);
+    BOOST_CHECK_EQUAL(tc->m_isCompleted, false);
     tc->m_isCompleted = true;
     --m_nPending;
 
@@ -102,22 +106,9 @@
 
 private:
   boost::asio::io_service m_io;
-  ssize_t m_nPending;
+  ssize_t m_nPending = 0;
 };
 
-void
-CanonizeFixture::addTest(const std::string& request,
-                         bool shouldSucceed, const std::string& expectedUri)
-{
-  ++m_nPending;
-  auto tc = make_shared<CanonizeTestCase>(request, shouldSucceed, expectedUri);
-
-  FaceUri uri(request);
-  uri.canonize(bind(&CanonizeFixture::onCanonizeSuccess, this, tc, _1),
-               bind(&CanonizeFixture::onCanonizeFailure, this, tc, _1),
-               m_io, time::seconds(10));
-}
-
 BOOST_AUTO_TEST_CASE(ParseInternal)
 {
   FaceUri uri;
@@ -167,7 +158,8 @@
 
   BOOST_CHECK_EQUAL(uri.parse("udp6://[2001:db8:3f9:0:3025:ccc5:eeeb:86dg]:6363"), false);
 
-  using namespace boost::asio;
+  namespace ip = boost::asio::ip;
+
   ip::udp::endpoint endpoint4(ip::address_v4::from_string("192.0.2.1"), 7777);
   BOOST_REQUIRE_NO_THROW(FaceUri(endpoint4));
   BOOST_CHECK_EQUAL(FaceUri(endpoint4).toString(), "udp4://192.0.2.1:7777");
@@ -177,7 +169,7 @@
   BOOST_CHECK_EQUAL(FaceUri(endpoint6).toString(), "udp6://[2001:db8::1]:7777");
 }
 
-BOOST_FIXTURE_TEST_CASE(CheckCanonicalUdp, CanonizeFixture)
+BOOST_FIXTURE_TEST_CASE(IsCanonicalUdp, CanonizeFixture)
 {
   BOOST_CHECK_EQUAL(FaceUri::canCanonize("udp"), true);
   BOOST_CHECK_EQUAL(FaceUri::canCanonize("udp4"), true);
@@ -195,6 +187,7 @@
   BOOST_CHECK_EQUAL(FaceUri("udp4://224.0.23.170:56363").isCanonical(), true);
 }
 
+BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(CanonizeUdpV4, 1)
 BOOST_FIXTURE_TEST_CASE(CanonizeUdpV4, CanonizeFixture)
 {
   SKIP_IF_IPV4_UNAVAILABLE();
@@ -206,6 +199,7 @@
   addTest("udp4://192.0.2.4:6363/", true, "udp4://192.0.2.4:6363");
   addTest("udp4://192.0.2.5:9695", true, "udp4://192.0.2.5:9695");
   addTest("udp4://192.0.2.666:6363", false, "");
+  addTest("udp4://192.0.2.7:99999", false, ""); // Bug #3897
   addTest("udp4://google-public-dns-a.google.com", true, "udp4://8.8.8.8:6363");
   addTest("udp4://google-public-dns-a.google.com:70000", false, "");
   addTest("udp4://invalid.invalid", false, "");
@@ -218,6 +212,7 @@
   runTests();
 }
 
+BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(CanonizeUdpV6, 1)
 BOOST_FIXTURE_TEST_CASE(CanonizeUdpV6, CanonizeFixture)
 {
   SKIP_IF_IPV6_UNAVAILABLE();
@@ -228,6 +223,7 @@
   addTest("udp://[2001:db8::1]:6363", true, "udp6://[2001:db8::1]:6363");
   addTest("udp6://[2001:db8::01]:6363", true, "udp6://[2001:db8::1]:6363");
   addTest("udp6://[2001::db8::1]:6363", false, "");
+  addTest("udp6://[2001:db8::1]:99999", false, ""); // Bug #3897
   addTest("udp6://google-public-dns-a.google.com", true, "udp6://[2001:4860:4860::8888]:6363");
   addTest("udp6://google-public-dns-a.google.com:70000", false, "");
   addTest("udp6://invalid.invalid", false, "");
@@ -253,7 +249,8 @@
   BOOST_CHECK_EQUAL(uri.parse("tcp://192.0.2.1:"), false);
   BOOST_CHECK_EQUAL(uri.parse("tcp://[::zzzz]"), false);
 
-  using namespace boost::asio;
+  namespace ip = boost::asio::ip;
+
   ip::tcp::endpoint endpoint4(ip::address_v4::from_string("192.0.2.1"), 7777);
   BOOST_REQUIRE_NO_THROW(FaceUri(endpoint4));
   BOOST_CHECK_EQUAL(FaceUri(endpoint4).toString(), "tcp4://192.0.2.1:7777");
@@ -266,7 +263,7 @@
   BOOST_CHECK_EQUAL(FaceUri(endpoint6).toString(), "tcp6://[2001:db8::1]:7777");
 }
 
-BOOST_FIXTURE_TEST_CASE(CheckCanonicalTcp, CanonizeFixture)
+BOOST_FIXTURE_TEST_CASE(IsCanonicalTcp, CanonizeFixture)
 {
   BOOST_CHECK_EQUAL(FaceUri::canCanonize("tcp"), true);
   BOOST_CHECK_EQUAL(FaceUri::canCanonize("tcp4"), true);
@@ -284,6 +281,7 @@
   BOOST_CHECK_EQUAL(FaceUri("tcp4://224.0.23.170:56363").isCanonical(), false);
 }
 
+BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(CanonizeTcpV4, 1)
 BOOST_FIXTURE_TEST_CASE(CanonizeTcpV4, CanonizeFixture)
 {
   SKIP_IF_IPV4_UNAVAILABLE();
@@ -295,6 +293,7 @@
   addTest("tcp4://192.0.2.4:6363/", true, "tcp4://192.0.2.4:6363");
   addTest("tcp4://192.0.2.5:9695", true, "tcp4://192.0.2.5:9695");
   addTest("tcp4://192.0.2.666:6363", false, "");
+  addTest("tcp4://192.0.2.7:99999", false, ""); // Bug #3897
   addTest("tcp4://google-public-dns-a.google.com", true, "tcp4://8.8.8.8:6363");
   addTest("tcp4://google-public-dns-a.google.com:70000", false, "");
   addTest("tcp4://invalid.invalid", false, "");
@@ -307,6 +306,7 @@
   runTests();
 }
 
+BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(CanonizeTcpV6, 1)
 BOOST_FIXTURE_TEST_CASE(CanonizeTcpV6, CanonizeFixture)
 {
   SKIP_IF_IPV6_UNAVAILABLE();
@@ -317,6 +317,7 @@
   addTest("tcp://[2001:db8::1]:6363", true, "tcp6://[2001:db8::1]:6363");
   addTest("tcp6://[2001:db8::01]:6363", true, "tcp6://[2001:db8::1]:6363");
   addTest("tcp6://[2001::db8::1]:6363", false, "");
+  addTest("tcp6://[2001:db8::1]:99999", false, ""); // Bug #3897
   addTest("tcp6://google-public-dns-a.google.com", true, "tcp6://[2001:4860:4860::8888]:6363");
   addTest("tcp6://google-public-dns-a.google.com:70000", false, "");
   addTest("tcp6://invalid.invalid", false, "");
@@ -329,6 +330,7 @@
   runTests();
 }
 
+BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(ParseUnix, 1)
 BOOST_AUTO_TEST_CASE(ParseUnix)
 {
   FaceUri uri;
@@ -339,15 +341,15 @@
   BOOST_CHECK_EQUAL(uri.getPort(), "");
   BOOST_CHECK_EQUAL(uri.getPath(), "/var/run/example.sock");
 
-  //BOOST_CHECK_EQUAL(uri.parse("unix://var/run/example.sock"), false);
-  // This is not a valid unix:/ URI, but the parse would treat "var" as host
+  // This is not a valid unix:// URI, but the parse would treat "var" as host
+  BOOST_CHECK_EQUAL(uri.parse("unix://var/run/example.sock"), false); // Bug #3896
 
-#ifdef HAVE_UNIX_SOCKETS
-  using namespace boost::asio;
-  local::stream_protocol::endpoint endpoint("/var/run/example.sock");
+#ifdef BOOST_ASIO_HAS_LOCAL_SOCKETS
+  using boost::asio::local::stream_protocol;
+  stream_protocol::endpoint endpoint("/var/run/example.sock");
   BOOST_REQUIRE_NO_THROW(FaceUri(endpoint));
   BOOST_CHECK_EQUAL(FaceUri(endpoint).toString(), "unix:///var/run/example.sock");
-#endif // HAVE_UNIX_SOCKETS
+#endif // BOOST_ASIO_HAS_LOCAL_SOCKETS
 }
 
 BOOST_AUTO_TEST_CASE(ParseFd)
@@ -377,7 +379,7 @@
 
   BOOST_CHECK_EQUAL(uri.parse("ether://[08:00:27:zz:dd:01]"), false);
 
-  ethernet::Address address = ethernet::Address::fromString("33:33:01:01:01:01");
+  auto address = ethernet::Address::fromString("33:33:01:01:01:01");
   BOOST_REQUIRE_NO_THROW(FaceUri(address));
   BOOST_CHECK_EQUAL(FaceUri(address).toString(), "ether://[33:33:01:01:01:01]");
 }
@@ -434,7 +436,7 @@
   BOOST_CHECK(!uri.parse("abc+://eth0"));
   BOOST_CHECK(!uri.parse("+abc://eth0"));
 
-  using namespace boost::asio;
+  namespace ip = boost::asio::ip;
 
   ip::udp::endpoint endpoint4(ip::udp::v4(), 7777);
   BOOST_REQUIRE_NO_THROW(FaceUri::fromUdpDev(endpoint4, "en1"));