route: use ndn::FaceUri type for faceUri

refs #4227

Change-Id: I1b0d7ed97e43e4d0c50770ed306cbe85382dfc9a
diff --git a/src/adjacency-list.hpp b/src/adjacency-list.hpp
index dd10082..eb99328 100644
--- a/src/adjacency-list.hpp
+++ b/src/adjacency-list.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -110,15 +110,6 @@
   AdjacencyList::iterator
   findAdjacent(const ndn::FaceUri& faceUri);
 
-  /*! \brief Hack to stop developers from using this function
-
-    It is here so that faceUri cannot be passed in as string,
-    converted to Name and findAdjacent(Name) be used.
-    So when faceUri is passed as string this will cause a compile error
-   */
-  void
-  findAdjacent(const std::string&) = delete;
-
   uint64_t
   getFaceId(const ndn::FaceUri& faceUri);
 
diff --git a/src/route/fib.cpp b/src/route/fib.cpp
index 0975c20..d47d880 100644
--- a/src/route/fib.cpp
+++ b/src/route/fib.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -242,10 +242,10 @@
 }
 
 void
-Fib::unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri)
+Fib::unregisterPrefix(const ndn::Name& namePrefix, const ndn::FaceUri& faceUri)
 {
   uint64_t faceId = 0;
-  auto adjacent = m_adjacencyList.findAdjacent(ndn::FaceUri(faceUri));
+  auto adjacent = m_adjacencyList.findAdjacent(faceUri);
   if (adjacent != m_adjacencyList.end()) {
     faceId = adjacent->getFaceId();
   }
diff --git a/src/route/fib.hpp b/src/route/fib.hpp
index 1a9b75f..8c53125 100644
--- a/src/route/fib.hpp
+++ b/src/route/fib.hpp
@@ -165,7 +165,7 @@
    *
    */
   void
-  unregisterPrefix(const ndn::Name& namePrefix, const std::string& faceUri);
+  unregisterPrefix(const ndn::Name& namePrefix, const ndn::FaceUri& faceUri);
 
   /*! \brief Log registration success, and update the Face ID associated with a URI.
    */
diff --git a/src/route/nexthop-list.hpp b/src/route/nexthop-list.hpp
index 98e5760..1ed1a5a 100644
--- a/src/route/nexthop-list.hpp
+++ b/src/route/nexthop-list.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -31,42 +31,16 @@
 
 namespace nlsr {
 
-struct NextHopComparator {
+struct NextHopUriSortedComparator
+{
   bool
-  operator() (const NextHop& nh1, const NextHop& nh2) const {
-    if (nh1.getRouteCostAsAdjustedInteger() < nh2.getRouteCostAsAdjustedInteger()) {
-      return true;
-    }
-    else if (nh1.getRouteCostAsAdjustedInteger() == nh2.getRouteCostAsAdjustedInteger()) {
-      return nh1.getConnectingFaceUri() < nh2.getConnectingFaceUri();
-    }
-    else {
-      return false;
-    }
+  operator()(const NextHop& lhs, const NextHop& rhs) const
+  {
+    return lhs.getConnectingFaceUri() < rhs.getConnectingFaceUri();
   }
 };
 
-struct NextHopUriSortedComparator {
-  bool
-  operator() (const NextHop& nh1, const NextHop& nh2) const {
-    return nh1.getConnectingFaceUri() < nh2.getConnectingFaceUri();
-  }
-};
-
-static inline bool
-nexthopAddCompare(const NextHop& nh1, const NextHop& nh2)
-{
-  return nh1.getConnectingFaceUri() == nh2.getConnectingFaceUri();
-}
-
-static inline bool
-nexthopRemoveCompare(const NextHop& nh1, const NextHop& nh2)
-{
-  return (nh1.getConnectingFaceUri() == nh2.getConnectingFaceUri() &&
-          nh1.getRouteCostAsAdjustedInteger() == nh2.getRouteCostAsAdjustedInteger()) ;
-}
-
-template<typename T = NextHopComparator>
+template<typename T = std::less<NextHop>>
 class NexthopListT
 {
 public:
@@ -76,19 +50,21 @@
     \param nh The next hop.
 
     Adds a next hop to this object. If the next hop is new it is
-    added. If the next hop already exists in the list then that next
-    hop's route cost is updated.
+    added. If the next hop already exists but has a higher cost then
+    its route cost is updated.
   */
   void
   addNextHop(const NextHop& nh)
   {
     auto it = std::find_if(m_nexthopList.begin(), m_nexthopList.end(),
-                           std::bind(&nexthopAddCompare, _1, nh));
+      [&nh] (const auto& item) {
+        return item.getConnectingFaceUri() == nh.getConnectingFaceUri();
+      });
     if (it == m_nexthopList.end()) {
       m_nexthopList.insert(nh);
     }
     else if (it->getRouteCost() > nh.getRouteCost()) {
-      removeNextHop(*it);
+      m_nexthopList.erase(it);
       m_nexthopList.insert(nh);
     }
   }
@@ -101,8 +77,7 @@
   void
   removeNextHop(const NextHop& nh)
   {
-    auto it = std::find_if(m_nexthopList.begin(), m_nexthopList.end(),
-                           std::bind(&nexthopRemoveCompare, _1, nh));
+    auto it = std::find(m_nexthopList.begin(), m_nexthopList.end(), nh);
     if (it != m_nexthopList.end()) {
       m_nexthopList.erase(it);
     }
diff --git a/src/route/nexthop.cpp b/src/route/nexthop.cpp
index a5f10ba..aeeb641 100644
--- a/src/route/nexthop.cpp
+++ b/src/route/nexthop.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -32,7 +32,7 @@
   size_t totalLength = 0;
 
   totalLength += ndn::encoding::prependDoubleBlock(block, nlsr::tlv::CostDouble, m_routeCost);
-  totalLength += ndn::encoding::prependStringBlock(block, nlsr::tlv::Uri, m_connectingFaceUri);
+  totalLength += ndn::encoding::prependStringBlock(block, nlsr::tlv::Uri, m_connectingFaceUri.toString());
 
   totalLength += block.prependVarNumber(totalLength);
   totalLength += block.prependVarNumber(nlsr::tlv::NextHop);
@@ -63,7 +63,7 @@
 void
 NextHop::wireDecode(const ndn::Block& wire)
 {
-  m_connectingFaceUri = "";
+  m_connectingFaceUri = {};
   m_routeCost = 0;
 
   m_wire = wire;
@@ -77,7 +77,12 @@
   auto val = m_wire.elements_begin();
 
   if (val != m_wire.elements_end() && val->type() == nlsr::tlv::Uri) {
-    m_connectingFaceUri = ndn::encoding::readString(*val);
+    try {
+      m_connectingFaceUri = ndn::FaceUri(ndn::encoding::readString(*val));
+    }
+    catch (const ndn::FaceUri::Error& e) {
+      NDN_THROW_NESTED(Error("Invalid Uri"));
+    }
     ++val;
   }
   else {
@@ -93,13 +98,6 @@
   }
 }
 
-bool
-operator==(const NextHop& lhs, const NextHop& rhs)
-{
-  return (lhs.getRouteCostAsAdjustedInteger() == rhs.getRouteCostAsAdjustedInteger()) &&
-         (lhs.getConnectingFaceUri() == rhs.getConnectingFaceUri());
-}
-
 std::ostream&
 operator<<(std::ostream& os, const NextHop& hop)
 {
diff --git a/src/route/nexthop.hpp b/src/route/nexthop.hpp
index 77bc8b1..6629d89 100644
--- a/src/route/nexthop.hpp
+++ b/src/route/nexthop.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -26,6 +26,9 @@
 #include <ndn-cxx/encoding/block.hpp>
 #include <ndn-cxx/encoding/encoding-buffer.hpp>
 #include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/net/face-uri.hpp>
+
+#include <boost/operators.hpp>
 
 #include <cmath>
 #include <ostream>
@@ -40,38 +43,33 @@
  *
  * \sa https://redmine.named-data.net/projects/nlsr/wiki/Routing_Table_Dataset
  */
-class NextHop
+class NextHop : private boost::totally_ordered<NextHop>
 {
 public:
   using Error = ndn::tlv::Error;
 
-  NextHop()
-    : m_connectingFaceUri()
-    , m_routeCost(0)
-    , m_isHyperbolic(false)
-  {
-  }
+  NextHop() = default;
 
-  NextHop(const std::string& cfu, double rc)
+  NextHop(const ndn::FaceUri& cfu, double rc)
     : m_connectingFaceUri(cfu)
     , m_routeCost(rc)
-    , m_isHyperbolic(false)
   {
   }
 
+  explicit
   NextHop(const ndn::Block& block)
   {
     wireDecode(block);
   }
 
-  const std::string&
+  const ndn::FaceUri&
   getConnectingFaceUri() const
   {
     return m_connectingFaceUri;
   }
 
   void
-  setConnectingFaceUri(const std::string& cfu)
+  setConnectingFaceUri(const ndn::FaceUri& cfu)
   {
     m_connectingFaceUri = cfu;
   }
@@ -124,10 +122,29 @@
   void
   wireDecode(const ndn::Block& wire);
 
+private: // non-member operators
+  // NOTE: the following "hidden friend" operators are available via
+  //       argument-dependent lookup only and must be defined inline.
+  // boost::totally_ordered provides !=, <=, >=, and > operators.
+
+  friend bool
+  operator==(const NextHop& lhs, const NextHop& rhs)
+  {
+    return lhs.getRouteCostAsAdjustedInteger() == rhs.getRouteCostAsAdjustedInteger() &&
+           lhs.getConnectingFaceUri() == rhs.getConnectingFaceUri();
+  }
+
+  friend bool
+  operator<(const NextHop& lhs, const NextHop& rhs)
+  {
+    return std::forward_as_tuple(lhs.getRouteCostAsAdjustedInteger(), lhs.getConnectingFaceUri()) <
+           std::forward_as_tuple(rhs.getRouteCostAsAdjustedInteger(), rhs.getConnectingFaceUri());
+  }
+
 private:
-  std::string m_connectingFaceUri;
-  double m_routeCost;
-  bool m_isHyperbolic;
+  ndn::FaceUri m_connectingFaceUri;
+  double m_routeCost = 0.0;
+  bool m_isHyperbolic = false;
 
   mutable ndn::Block m_wire;
 
@@ -147,9 +164,6 @@
 
 NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(NextHop);
 
-bool
-operator==(const NextHop& lhs, const NextHop& rhs);
-
 std::ostream&
 operator<<(std::ostream& os, const NextHop& hop);
 
diff --git a/src/route/routing-table-calculator.cpp b/src/route/routing-table-calculator.cpp
index a7419ce..54c8a47 100644
--- a/src/route/routing-table-calculator.cpp
+++ b/src/route/routing-table-calculator.cpp
@@ -348,8 +348,7 @@
         // Fetch its actual name
         auto nextHopRouterName = pMap.getRouterNameByMappingNo(nextHopRouter);
         if (nextHopRouterName) {
-          std::string nextHopFace =
-            adjacencies.getAdjacent(*nextHopRouterName).getFaceUri().toString();
+          auto nextHopFace = adjacencies.getAdjacent(*nextHopRouterName).getFaceUri();
           // Add next hop to routing table
           NextHop nh(nextHopFace, routeCost);
           rt.addNextHop(*(pMap.getRouterNameByMappingNo(i)), nh);
@@ -451,10 +450,8 @@
       continue;
     }
 
-    std::string srcFaceUri = adj->getFaceUri().toString();
-
     // Install nexthops for this router to the neighbor; direct neighbors have a 0 cost link
-    addNextHop(srcRouterName, srcFaceUri, 0, rt);
+    addNextHop(srcRouterName, adj->getFaceUri(), 0, rt);
 
     auto src = map.getMappingNoByRouterName(srcRouterName);
     if (!src) {
@@ -477,7 +474,7 @@
                            << " to " << *destRouterName);
             continue;
           }
-          addNextHop(*destRouterName, srcFaceUri, distance, rt);
+          addNextHop(*destRouterName, adj->getFaceUri(), distance, rt);
         }
       }
     }
@@ -618,7 +615,7 @@
 }
 
 void
-HyperbolicRoutingCalculator::addNextHop(ndn::Name dest, std::string faceUri,
+HyperbolicRoutingCalculator::addNextHop(const ndn::Name& dest, const ndn::FaceUri& faceUri,
                                         double cost, RoutingTable& rt)
 {
   NextHop hop(faceUri, cost);
diff --git a/src/route/routing-table-calculator.hpp b/src/route/routing-table-calculator.hpp
index 749c5b8..45af713 100644
--- a/src/route/routing-table-calculator.hpp
+++ b/src/route/routing-table-calculator.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -214,7 +214,7 @@
   getHyperbolicDistance(Lsdb& lsdb, ndn::Name src, ndn::Name dest);
 
   void
-  addNextHop(ndn::Name destinationRouter, std::string faceUri, double cost, RoutingTable& rt);
+  addNextHop(const ndn::Name& destinationRouter, const ndn::FaceUri& faceUri, double cost, RoutingTable& rt);
 
   double
   calculateHyperbolicDistance(double rI, double rJ, double deltaTheta);
diff --git a/tests/publisher/publisher-fixture.hpp b/tests/publisher/publisher-fixture.hpp
index b187ffb..43c61b7 100644
--- a/tests/publisher/publisher-fixture.hpp
+++ b/tests/publisher/publisher-fixture.hpp
@@ -56,7 +56,7 @@
   NextHop
   createNextHop(const std::string& faceUri, double cost)
   {
-    return {faceUri, cost};
+    return {ndn::FaceUri(faceUri), cost};
   }
 
   CoordinateLsa
diff --git a/tests/route/test-fib.cpp b/tests/route/test-fib.cpp
index 7bbfccb..d90d125 100644
--- a/tests/route/test-fib.cpp
+++ b/tests/route/test-fib.cpp
@@ -31,6 +31,16 @@
 namespace nlsr {
 namespace test {
 
+static const ndn::Name router1Name = "/ndn/router1";
+static const ndn::Name router2Name = "/ndn/router2";
+static const ndn::Name router3Name = "/ndn/router3";
+static const ndn::FaceUri router1FaceUri("udp4://10.0.0.1:6363");
+static const ndn::FaceUri router2FaceUri("udp4://10.0.0.2:6363");
+static const ndn::FaceUri router3FaceUri("udp4://10.0.0.3:6363");
+constexpr uint32_t router1FaceId = 1;
+constexpr uint32_t router2FaceId = 2;
+constexpr uint32_t router3FaceId = 3;
+
 class FibFixture : public IoKeyChainFixture
 {
 public:
@@ -41,13 +51,13 @@
   {
     advanceClocks(1_s);
 
-    Adjacent neighbor1(router1Name, ndn::FaceUri(router1FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
+    Adjacent neighbor1(router1Name, router1FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router1FaceId);
     adjacencies.insert(neighbor1);
 
-    Adjacent neighbor2(router2Name, ndn::FaceUri(router2FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
+    Adjacent neighbor2(router2Name, router2FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router2FaceId);
     adjacencies.insert(neighbor2);
 
-    Adjacent neighbor3(router3Name, ndn::FaceUri(router3FaceUri), 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
+    Adjacent neighbor3(router3Name, router3FaceUri, 0, Adjacent::STATUS_ACTIVE, 0, router3FaceId);
     adjacencies.insert(neighbor3);
 
     conf.setMaxFacesPerPrefix(2);
@@ -81,32 +91,8 @@
   AdjacencyList& adjacencies;
   Fib fib;
   std::vector<ndn::Interest>& interests;
-
-  static const ndn::Name router1Name;
-  static const ndn::Name router2Name;
-  static const ndn::Name router3Name;
-
-  static const std::string router1FaceUri;
-  static const std::string router2FaceUri;
-  static const std::string router3FaceUri;
-
-  static const uint32_t router1FaceId;
-  static const uint32_t router2FaceId;
-  static const uint32_t router3FaceId;
 };
 
-const ndn::Name FibFixture::router1Name = "/ndn/router1";
-const ndn::Name FibFixture::router2Name = "/ndn/router2";
-const ndn::Name FibFixture::router3Name = "/ndn/router3";
-
-const std::string FibFixture::router1FaceUri = "udp4://10.0.0.1";
-const std::string FibFixture::router2FaceUri = "udp4://10.0.0.2";
-const std::string FibFixture::router3FaceUri = "udp4://10.0.0.3";
-
-const uint32_t FibFixture::router1FaceId = 1;
-const uint32_t FibFixture::router2FaceId = 2;
-const uint32_t FibFixture::router3FaceId = 3;
-
 BOOST_FIXTURE_TEST_SUITE(TestFib, FibFixture)
 
 BOOST_AUTO_TEST_CASE(NextHopsAdd)
@@ -367,16 +353,16 @@
 
   // Wustl advertises /test
   NexthopList nhl1;
-  nhl1.addNextHop(NextHop("udp4://10.0.0.13:6363", 28));
-  nhl1.addNextHop(NextHop("udp4://10.0.0.9:6363", 38));
-  nhl1.addNextHop(NextHop("udp4://10.0.0.26:6363", 44));
+  nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 28));
+  nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 38));
+  nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 44));
   fib.update("/test", nhl1);
 
   // Memphis advertises /test
   NexthopList nhl2;
-  nhl2.addNextHop(NextHop("udp4://10.0.0.9:6363", 21));
-  nhl2.addNextHop(NextHop("udp4://10.0.0.13:6363", 26));
-  nhl2.addNextHop(NextHop("udp4://10.0.0.26:6363", 42));
+  nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 21));
+  nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 26));
+  nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 42));
   fib.update("/test", nhl2);
 
   advanceClocks(10_ms);
diff --git a/tests/route/test-hyperbolic-calculator.cpp b/tests/route/test-hyperbolic-calculator.cpp
index 10a401e..0d4dd5e 100644
--- a/tests/route/test-hyperbolic-calculator.cpp
+++ b/tests/route/test-hyperbolic-calculator.cpp
@@ -33,9 +33,15 @@
 namespace nlsr {
 namespace test {
 
-using std::shared_ptr;
 using ndn::time::system_clock;
 
+static const ndn::Name ROUTER_A_NAME = "/ndn/router/a";
+static const ndn::Name ROUTER_B_NAME = "/ndn/router/b";
+static const ndn::Name ROUTER_C_NAME = "/ndn/router/c";
+static const ndn::FaceUri ROUTER_A_FACE("udp4://10.0.0.1:6363");
+static const ndn::FaceUri ROUTER_B_FACE("udp4://10.0.0.2:6363");
+static const ndn::FaceUri ROUTER_C_FACE("udp4://10.0.0.3:6363");
+
 constexpr system_clock::time_point MAX_TIME = system_clock::time_point::max();
 
 class HyperbolicCalculatorFixture : public IoKeyChainFixture
@@ -112,8 +118,8 @@
     NexthopList& bHopList = entryB->getNexthopList();
     BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
 
-    for (std::set<NextHop, NextHopComparator>::iterator it = bHopList.begin(); it != bHopList.end(); ++it) {
-      std::string faceUri = it->getConnectingFaceUri();
+    for (auto it = bHopList.begin(); it != bHopList.end(); ++it) {
+      auto faceUri = it->getConnectingFaceUri();
       uint64_t cost = it->getRouteCostAsAdjustedInteger();
 
       BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == 0) ||
@@ -126,8 +132,8 @@
     NexthopList& cHopList = entryC->getNexthopList();
     BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
 
-    for (std::set<NextHop, NextHopComparator>::iterator it = cHopList.begin(); it != cHopList.end(); ++it) {
-      std::string faceUri = it->getConnectingFaceUri();
+    for (auto it = cHopList.begin(); it != cHopList.end(); ++it) {
+      auto faceUri = it->getConnectingFaceUri();
       uint64_t cost = it->getRouteCostAsAdjustedInteger();
 
       BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == applyHyperbolicFactorAndRound(expectedCost)) ||
@@ -153,24 +159,8 @@
   RoutingTable& routingTable;
   AdjacencyList& adjacencies;
   Lsdb& lsdb;
-
-  static const ndn::Name ROUTER_A_NAME;
-  static const ndn::Name ROUTER_B_NAME;
-  static const ndn::Name ROUTER_C_NAME;
-
-  static const std::string ROUTER_A_FACE;
-  static const std::string ROUTER_B_FACE;
-  static const std::string ROUTER_C_FACE;
 };
 
-const ndn::Name HyperbolicCalculatorFixture::ROUTER_A_NAME = "/ndn/router/a";
-const ndn::Name HyperbolicCalculatorFixture::ROUTER_B_NAME = "/ndn/router/b";
-const ndn::Name HyperbolicCalculatorFixture::ROUTER_C_NAME = "/ndn/router/c";
-
-const std::string HyperbolicCalculatorFixture::ROUTER_A_FACE = "udp4://10.0.0.1";
-const std::string HyperbolicCalculatorFixture::ROUTER_B_FACE = "udp4://10.0.0.2";
-const std::string HyperbolicCalculatorFixture::ROUTER_C_FACE = "udp4://10.0.0.3";
-
 BOOST_FIXTURE_TEST_SUITE(TestHyperbolicRoutingCalculator, HyperbolicCalculatorFixture)
 
 BOOST_AUTO_TEST_CASE(Basic)
diff --git a/tests/route/test-link-state-calculator.cpp b/tests/route/test-link-state-calculator.cpp
index 0a4c522..73421b0 100644
--- a/tests/route/test-link-state-calculator.cpp
+++ b/tests/route/test-link-state-calculator.cpp
@@ -35,6 +35,15 @@
 namespace test {
 
 constexpr ndn::time::system_clock::time_point MAX_TIME = ndn::time::system_clock::time_point::max();
+static const ndn::Name ROUTER_A_NAME = "/ndn/site/%C1.Router/this-router";
+static const ndn::Name ROUTER_B_NAME = "/ndn/site/%C1.Router/b";
+static const ndn::Name ROUTER_C_NAME = "/ndn/site/%C1.Router/c";
+static const ndn::FaceUri ROUTER_A_FACE("udp4://10.0.0.1");
+static const ndn::FaceUri ROUTER_B_FACE("udp4://10.0.0.2");
+static const ndn::FaceUri ROUTER_C_FACE("udp4://10.0.0.3");
+constexpr double LINK_AB_COST = 5;
+constexpr double LINK_AC_COST = 10;
+constexpr double LINK_BC_COST = 17;
 
 class LinkStateCalculatorFixture : public IoKeyChainFixture
 {
@@ -53,9 +62,9 @@
   // Triangle topology with routers A, B, C connected
   void setUpTopology()
   {
-    Adjacent a(ROUTER_A_NAME, ndn::FaceUri(ROUTER_A_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
-    Adjacent b(ROUTER_B_NAME, ndn::FaceUri(ROUTER_B_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
-    Adjacent c(ROUTER_C_NAME, ndn::FaceUri(ROUTER_C_FACE), 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent a(ROUTER_A_NAME, ROUTER_A_FACE, 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent b(ROUTER_B_NAME, ROUTER_B_FACE, 0, Adjacent::STATUS_ACTIVE, 0, 0);
+    Adjacent c(ROUTER_C_NAME, ROUTER_C_FACE, 0, Adjacent::STATUS_ACTIVE, 0, 0);
 
     // Router A
     b.setLinkCost(LINK_AB_COST);
@@ -103,32 +112,8 @@
 
   RoutingTable& routingTable;
   Lsdb& lsdb;
-
-  static const ndn::Name ROUTER_A_NAME;
-  static const ndn::Name ROUTER_B_NAME;
-  static const ndn::Name ROUTER_C_NAME;
-
-  static const std::string ROUTER_A_FACE;
-  static const std::string ROUTER_B_FACE;
-  static const std::string ROUTER_C_FACE;
-
-  static const double LINK_AB_COST;
-  static const double LINK_AC_COST;
-  static const double LINK_BC_COST;
 };
 
-const ndn::Name LinkStateCalculatorFixture::ROUTER_A_NAME = "/ndn/site/%C1.Router/this-router";
-const ndn::Name LinkStateCalculatorFixture::ROUTER_B_NAME = "/ndn/site/%C1.Router/b";
-const ndn::Name LinkStateCalculatorFixture::ROUTER_C_NAME = "/ndn/site/%C1.Router/c";
-
-const std::string LinkStateCalculatorFixture::ROUTER_A_FACE = "udp4://10.0.0.1";
-const std::string LinkStateCalculatorFixture::ROUTER_B_FACE = "udp4://10.0.0.2";
-const std::string LinkStateCalculatorFixture::ROUTER_C_FACE = "udp4://10.0.0.3";
-
-const double LinkStateCalculatorFixture::LINK_AB_COST = 5;
-const double LinkStateCalculatorFixture::LINK_AC_COST = 10;
-const double LinkStateCalculatorFixture::LINK_BC_COST = 17;
-
 BOOST_FIXTURE_TEST_SUITE(TestLinkStateRoutingCalculator, LinkStateCalculatorFixture)
 
 BOOST_AUTO_TEST_CASE(Basic)
@@ -144,7 +129,7 @@
   BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
 
   for (const NextHop& hop : bHopList) {
-    std::string faceUri = hop.getConnectingFaceUri();
+    auto faceUri = hop.getConnectingFaceUri();
     uint64_t cost = hop.getRouteCostAsAdjustedInteger();
 
     BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
@@ -160,7 +145,7 @@
   BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
 
   for (const NextHop& hop : cHopList) {
-    std::string faceUri = hop.getConnectingFaceUri();
+    auto faceUri = hop.getConnectingFaceUri();
     uint64_t cost = hop.getRouteCostAsAdjustedInteger();
 
     BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
@@ -192,7 +177,7 @@
   BOOST_REQUIRE_EQUAL(bHopList.getNextHops().size(), 2);
 
   for (const NextHop& hop : bHopList) {
-    std::string faceUri = hop.getConnectingFaceUri();
+    auto faceUri = hop.getConnectingFaceUri();
     uint64_t cost = hop.getRouteCostAsAdjustedInteger();
 
     BOOST_CHECK((faceUri == ROUTER_B_FACE && cost == LINK_AB_COST) ||
@@ -208,7 +193,7 @@
   BOOST_REQUIRE_EQUAL(cHopList.getNextHops().size(), 2);
 
   for (const NextHop& hop : cHopList) {
-    std::string faceUri = hop.getConnectingFaceUri();
+    auto faceUri = hop.getConnectingFaceUri();
     uint64_t cost = hop.getRouteCostAsAdjustedInteger();
 
     BOOST_CHECK((faceUri == ROUTER_C_FACE && cost == LINK_AC_COST) ||
diff --git a/tests/route/test-name-prefix-table.cpp b/tests/route/test-name-prefix-table.cpp
index 839c874..6181296 100644
--- a/tests/route/test-name-prefix-table.cpp
+++ b/tests/route/test-name-prefix-table.cpp
@@ -274,9 +274,9 @@
 BOOST_FIXTURE_TEST_CASE(RoutingTableUpdate, NamePrefixTableFixture)
 {
   const ndn::Name destination = ndn::Name{"/ndn/destination1"};
-  NextHop hop1{"upd4://10.0.0.1", 0};
-  NextHop hop2{"udp4://10.0.0.2", 1};
-  NextHop hop3{"udp4://10.0.0.3", 2};
+  NextHop hop1{ndn::FaceUri("upd4://10.0.0.1"), 0};
+  NextHop hop2{ndn::FaceUri("upd4://10.0.0.2"), 1};
+  NextHop hop3{ndn::FaceUri("upd4://10.0.0.3"), 2};
   const NamePrefixTableEntry entry1{"/ndn/router1"};
   npt.addEntry(entry1.getNamePrefix(), destination);
 
diff --git a/tests/route/test-nexthop-list.cpp b/tests/route/test-nexthop-list.cpp
index 73108dc..5801104 100644
--- a/tests/route/test-nexthop-list.cpp
+++ b/tests/route/test-nexthop-list.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2021,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -86,14 +86,14 @@
 
 BOOST_AUTO_TEST_CASE(TieBreaker)
 {
-  // equal-cost hops are sorted lexicographically
+  // equal-cost hops are sorted consistently
   NextHop hopA;
   hopA.setRouteCost(25);
-  hopA.setConnectingFaceUri("AAAZZ");
+  hopA.setConnectingFaceUri(ndn::FaceUri("udp4://192.168.3.1:6363"));
 
   NextHop hopZ;
   hopZ.setRouteCost(25);
-  hopZ.setConnectingFaceUri("ZZA");
+  hopZ.setConnectingFaceUri(ndn::FaceUri("udp4://192.168.3.9:6363"));
 
   NexthopList list;
   list.addNextHop(hopA);
@@ -108,32 +108,15 @@
 
   it = list.begin();
   BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), hopA.getConnectingFaceUri());
-
-
-  // equal-cost and lexicographically equal hops are sorted by the length of their face uris
-  NextHop longUriHop;
-  longUriHop.setRouteCost(25);
-  longUriHop.setConnectingFaceUri("AAAAAA");
-
-  NextHop shortUriHop;
-  shortUriHop.setRouteCost(25);
-  shortUriHop.setConnectingFaceUri("AAA");
-
-  list.clear();
-  list.addNextHop(longUriHop);
-  list.addNextHop(shortUriHop);
-
-  it = list.begin();
-  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), shortUriHop.getConnectingFaceUri());
 }
 
 BOOST_AUTO_TEST_CASE(SortOnAddAndRemove)
 {
   NexthopList list;
 
-  NextHop hopA("A", 10);
-  NextHop hopB("B", 5);
-  NextHop hopC("C", 25);
+  NextHop hopA(ndn::FaceUri("udp4://192.168.3.1:6363"), 10);
+  NextHop hopB(ndn::FaceUri("udp4://192.168.3.2:6363"), 5);
+  NextHop hopC(ndn::FaceUri("udp4://192.168.3.3:6363"), 25);
 
   list.addNextHop(hopA);
   list.addNextHop(hopB);
@@ -168,8 +151,8 @@
 {
   NexthopList list;
 
-  NextHop hopA("udp4://10.0.0.1:6363", 10);
-  NextHop hopB("udp4://10.0.0.1:6363", 5);
+  NextHop hopA(ndn::FaceUri("udp4://10.0.0.1:6363"), 10);
+  NextHop hopB(ndn::FaceUri("udp4://10.0.0.1:6363"), 5);
 
   list.addNextHop(hopA);
   list.addNextHop(hopB);
@@ -191,33 +174,32 @@
   // If default sorter is used then difference results in
   // the same hops to remove as those that were added
   NexthopList nhl1;
-  nhl1.addNextHop(NextHop("udp4://10.0.0.13:6363", 28));
-  nhl1.addNextHop(NextHop("udp4://10.0.0.9:6363", 38));
-  nhl1.addNextHop(NextHop("udp4://10.0.0.26:6363", 44));
+  nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 28));
+  nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 38));
+  nhl1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 44));
 
   NexthopList nhl2;
-  nhl2.addNextHop(NextHop("udp4://10.0.0.9:6363", 21));
-  nhl2.addNextHop(NextHop("udp4://10.0.0.13:6363", 26));
-  nhl2.addNextHop(NextHop("udp4://10.0.0.26:6363", 42));
+  nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 21));
+  nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 26));
+  nhl2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 42));
 
-  std::set<NextHop, NextHopComparator> hopsToRemove;
+  std::set<NextHop> hopsToRemove;
   std::set_difference(nhl2.begin(), nhl2.end(),
                       nhl1.begin(), nhl1.end(),
-                      std::inserter(hopsToRemove, hopsToRemove.begin()),
-                      NextHopComparator());
+                      std::inserter(hopsToRemove, hopsToRemove.begin()));
 
   BOOST_CHECK_EQUAL(hopsToRemove.size(), 3);
 
   // Sorted by FaceUri
   NextHopsUriSortedSet nhs1;
-  nhs1.addNextHop(NextHop("udp4://10.0.0.13:6363", 28));
-  nhs1.addNextHop(NextHop("udp4://10.0.0.9:6363", 38));
-  nhs1.addNextHop(NextHop("udp4://10.0.0.26:6363", 44));
+  nhs1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 28));
+  nhs1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 38));
+  nhs1.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 44));
 
   NextHopsUriSortedSet nhs2;
-  nhs2.addNextHop(NextHop("udp4://10.0.0.9:6363", 21));
-  nhs2.addNextHop(NextHop("udp4://10.0.0.13:6363", 26));
-  nhs2.addNextHop(NextHop("udp4://10.0.0.26:6363", 42));
+  nhs2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.9:6363"), 21));
+  nhs2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.13:6363"), 26));
+  nhs2.addNextHop(NextHop(ndn::FaceUri("udp4://10.0.0.26:6363"), 42));
 
   std::set<NextHop, NextHopUriSortedComparator> hopsToRemove2;
   std::set_difference(nhs2.begin(), nhs2.end(),
diff --git a/tests/route/test-nexthop.cpp b/tests/route/test-nexthop.cpp
index 3ba3539..9d80c1f 100644
--- a/tests/route/test-nexthop.cpp
+++ b/tests/route/test-nexthop.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -26,6 +26,9 @@
 
 BOOST_AUTO_TEST_SUITE(TestNexthop)
 
+static const ndn::FaceUri faceUri1("udp4://192.168.3.1:6363");
+static const ndn::FaceUri faceUri2("udp4://192.168.3.2:6363");
+
 static double
 getHyperbolicAdjustedDecimal(unsigned int i)
 {
@@ -41,16 +44,23 @@
 BOOST_AUTO_TEST_CASE(LinkStateSetAndGet)
 {
   NextHop hop1;
-  hop1.setConnectingFaceUri("udp://test/uri");
+  hop1.setConnectingFaceUri(faceUri1);
   hop1.setRouteCost(12.34);
-
-  BOOST_CHECK_EQUAL(hop1.getConnectingFaceUri(), "udp://test/uri");
+  BOOST_CHECK_EQUAL(hop1.getConnectingFaceUri(), faceUri1);
   BOOST_CHECK_EQUAL(hop1.getRouteCost(), 12.34);
   BOOST_CHECK_EQUAL(hop1.getRouteCostAsAdjustedInteger(), 12);
 
-  NextHop hop2;
+  NextHop hop2(faceUri2, 12.34);
+  BOOST_CHECK_NE(hop1, hop2);
+  BOOST_CHECK_LT(hop1, hop2);
+  BOOST_CHECK_LE(hop1, hop2);
+  BOOST_CHECK_GT(hop2, hop1);
+  BOOST_CHECK_GE(hop2, hop1);
 
-  hop2.setRouteCost(12.34);
+  hop2.setConnectingFaceUri(faceUri1);
+  BOOST_CHECK_EQUAL(hop1, hop2);
+  BOOST_CHECK_LE(hop1, hop2);
+  BOOST_CHECK_GE(hop2, hop1);
   BOOST_CHECK_EQUAL(hop1.getRouteCostAsAdjustedInteger(), hop2.getRouteCostAsAdjustedInteger());
 }
 
@@ -58,31 +68,37 @@
 {
   NextHop hop1;
   hop1.setHyperbolic(true);
-  hop1.setConnectingFaceUri("udp://test/uri");
+  hop1.setConnectingFaceUri(faceUri1);
   hop1.setRouteCost(12.34);
-
-  BOOST_CHECK_EQUAL(hop1.getConnectingFaceUri(), "udp://test/uri");
+  BOOST_CHECK_EQUAL(hop1.getConnectingFaceUri(), faceUri1);
   BOOST_CHECK_EQUAL(hop1.getRouteCost(), 12.34);
   BOOST_CHECK_EQUAL(hop1.getRouteCostAsAdjustedInteger(), applyHyperbolicFactorAndRound(12.34));
 
-  NextHop hop2;
+  NextHop hop2(faceUri2, 12.34);
   hop2.setHyperbolic(true);
+  BOOST_CHECK_NE(hop1, hop2);
+  BOOST_CHECK_LT(hop1, hop2);
+  BOOST_CHECK_LE(hop1, hop2);
+  BOOST_CHECK_GT(hop2, hop1);
+  BOOST_CHECK_GE(hop2, hop1);
 
-  hop2.setRouteCost(12.34);
+  hop2.setConnectingFaceUri(faceUri1);
+  BOOST_CHECK_EQUAL(hop1, hop2);
   BOOST_CHECK_EQUAL(hop1.getRouteCostAsAdjustedInteger(), hop2.getRouteCostAsAdjustedInteger());
 
   hop2.setRouteCost(12.35);
-  BOOST_CHECK(hop1.getRouteCostAsAdjustedInteger() < hop2.getRouteCostAsAdjustedInteger());
+  BOOST_CHECK_LT(hop1, hop2);
+  BOOST_CHECK_LT(hop1.getRouteCostAsAdjustedInteger(), hop2.getRouteCostAsAdjustedInteger());
 }
 
 BOOST_AUTO_TEST_CASE(HyperbolicRound)
 {
   NextHop hop1;
   hop1.setHyperbolic(true);
-  hop1.setConnectingFaceUri("udp://test/uri");
+  hop1.setConnectingFaceUri(faceUri1);
   hop1.setRouteCost(1 + getHyperbolicAdjustedDecimal(6));
 
-  BOOST_CHECK_EQUAL(hop1.getConnectingFaceUri(), "udp://test/uri");
+  BOOST_CHECK_EQUAL(hop1.getConnectingFaceUri(), faceUri1);
   BOOST_CHECK_EQUAL(hop1.getRouteCost(), 1 + getHyperbolicAdjustedDecimal(6));
   BOOST_CHECK_EQUAL(hop1.getRouteCostAsAdjustedInteger(),
                     applyHyperbolicFactorAndRound((1 + getHyperbolicAdjustedDecimal(6))));
@@ -97,47 +113,47 @@
   BOOST_CHECK_EQUAL(hop1.getRouteCostAsAdjustedInteger(), hop2.getRouteCostAsAdjustedInteger());
 
   hop2.setRouteCost(1 + getHyperbolicAdjustedDecimal(4));
-  BOOST_CHECK(hop1.getRouteCostAsAdjustedInteger() > hop2.getRouteCostAsAdjustedInteger());
+  BOOST_CHECK_GT(hop1.getRouteCostAsAdjustedInteger(), hop2.getRouteCostAsAdjustedInteger());
 }
 
 const uint8_t NexthopData[] =
 {
   // Header
-  0x8f, 0x1d,
+  0x8f, 0x23,
   // Uri
-  0x8d, 0x11, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f,
-  0x70, 0x2f, 0x74, 0x6c, 0x76,
+  0x8d, 0x17, 0x75, 0x64, 0x70, 0x34, 0x3a, 0x2f, 0x2f, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38,
+  0x2e, 0x33, 0x2e, 0x31, 0x3a, 0x36, 0x33, 0x36, 0x33,
   // Cost
   0x86, 0x08, 0x3f, 0xfa, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66
 };
 
-BOOST_AUTO_TEST_CASE(NexthopEncode)
+BOOST_AUTO_TEST_CASE(Encode)
 {
   NextHop nexthops1;
-  nexthops1.setConnectingFaceUri("/test/nexthop/tlv");
+  nexthops1.setConnectingFaceUri(faceUri1);
   nexthops1.setRouteCost(1.65);
 
   BOOST_TEST(nexthops1.wireEncode() == NexthopData, boost::test_tools::per_element());
 }
 
-BOOST_AUTO_TEST_CASE(NexthopDecode)
+BOOST_AUTO_TEST_CASE(Decode)
 {
   NextHop nexthops1;
   nexthops1.wireDecode(ndn::Block{NexthopData});
 
-  BOOST_REQUIRE_EQUAL(nexthops1.getConnectingFaceUri(), "/test/nexthop/tlv");
+  BOOST_REQUIRE_EQUAL(nexthops1.getConnectingFaceUri(), faceUri1);
   BOOST_REQUIRE_EQUAL(nexthops1.getRouteCost(), 1.65);
 }
 
-BOOST_AUTO_TEST_CASE(AdjacencyOutputStream)
+BOOST_AUTO_TEST_CASE(OutputStream)
 {
   NextHop nexthops1;
-  nexthops1.setConnectingFaceUri("/test/nexthop/tlv");
+  nexthops1.setConnectingFaceUri(faceUri1);
   nexthops1.setRouteCost(99);
 
   std::ostringstream os;
   os << nexthops1;
-  BOOST_CHECK_EQUAL(os.str(), "NextHop(Uri: /test/nexthop/tlv, Cost: 99)");
+  BOOST_CHECK_EQUAL(os.str(), "NextHop(Uri: udp4://192.168.3.1:6363, Cost: 99)");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/route/test-routing-table-entry.cpp b/tests/route/test-routing-table-entry.cpp
index f30e17e..9d685ae 100644
--- a/tests/route/test-routing-table-entry.cpp
+++ b/tests/route/test-routing-table-entry.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2022,  The University of Memphis,
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -33,20 +33,31 @@
   BOOST_CHECK_EQUAL(rte1.getDestination(), "router1");
 }
 
-const uint8_t RoutingTableEntryWithNexthopsData[] = {
+static const ndn::FaceUri NEXTHOP1("udp4://192.168.3.1:6363");
+static const ndn::FaceUri NEXTHOP2("udp4://192.168.3.2:6363");
+
+static const uint8_t RoutingTableEntryWithNexthopsData[] = {
   // Header
-  0x91, 0x35,
+  0x91, 0x53,
   // Destination Name
-  0x07, 0x07, 0x08, 0x05, 0x64, 0x65, 0x73, 0x74, 0x31, 0x8f, 0x14,
+  0x07, 0x07, 0x08, 0x05, 0x64, 0x65, 0x73, 0x74, 0x31,
   // Nexthop
-  0x8d, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x31, 0x86, 0x08, 0x3f, 0xfa,
-  0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x8f, 0x14, 0x8d, 0x08,
+  0x8f, 0x23,
+  // Nexthop.Uri
+  0x8d, 0x17, 0x75, 0x64, 0x70, 0x34, 0x3a, 0x2f, 0x2f, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38,
+  0x2e, 0x33, 0x2e, 0x31, 0x3a, 0x36, 0x33, 0x36, 0x33,
+  // Nexthop.CostDouble
+  0x86, 0x08, 0x3f, 0xfa, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
   // Nexthop
-  0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x32, 0x86, 0x08, 0x3f, 0xfa, 0x66, 0x66,
-  0x66, 0x66, 0x66, 0x66
+  0x8f, 0x23,
+  // Nexthop.Uri
+  0x8d, 0x17, 0x75, 0x64, 0x70, 0x34, 0x3a, 0x2f, 0x2f, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38,
+  0x2e, 0x33, 0x2e, 0x32, 0x3a, 0x36, 0x33, 0x36, 0x33,
+  // Nexthop.CostDouble
+  0x86, 0x08, 0x3f, 0xfa, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
 };
 
-const uint8_t RoutingTableEntryWithoutNexthopsData[] = {
+static const uint8_t RoutingTableEntryWithoutNexthopsData[] = {
   // Header
   0x91, 0x09,
   // Destination Name
@@ -58,12 +69,12 @@
   RoutingTableEntry rte(ndn::Name("dest1"));
 
   NextHop nexthops1;
-  nexthops1.setConnectingFaceUri("nexthop1");
+  nexthops1.setConnectingFaceUri(NEXTHOP1);
   nexthops1.setRouteCost(1.65);
   rte.getNexthopList().addNextHop(nexthops1);
 
   NextHop nexthops2;
-  nexthops2.setConnectingFaceUri("nexthop2");
+  nexthops2.setConnectingFaceUri(NEXTHOP2);
   nexthops2.setRouteCost(1.65);
   rte.getNexthopList().addNextHop(nexthops2);
 
@@ -78,11 +89,11 @@
 
   BOOST_CHECK(rte.getNexthopList().size() != 0);
   auto it = rte.getNexthopList().begin();
-  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), "nexthop1");
+  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), NEXTHOP1);
   BOOST_CHECK_EQUAL(it->getRouteCost(), 1.65);
 
   it++;
-  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), "nexthop2");
+  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), NEXTHOP2);
   BOOST_CHECK_EQUAL(it->getRouteCost(), 1.65);
 }
 
@@ -105,45 +116,41 @@
   RoutingTableEntry rte(ndn::Name("dest1"));
 
   NextHop nexthops1;
-  nexthops1.setConnectingFaceUri("nexthop1");
+  nexthops1.setConnectingFaceUri(NEXTHOP1);
   nexthops1.setRouteCost(99);
   rte.getNexthopList().addNextHop(nexthops1);
 
   BOOST_CHECK_EQUAL(rte.getNexthopList().size(), 1);
 
   auto it = rte.getNexthopList().begin();
-  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), "nexthop1");
+  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), NEXTHOP1);
   BOOST_CHECK_EQUAL(it->getRouteCost(), 99);
 
   rte.getNexthopList().clear();
   BOOST_CHECK_EQUAL(rte.getNexthopList().size(), 0);
 
   NextHop nexthops2;
-  nexthops2.setConnectingFaceUri("nexthop2");
+  nexthops2.setConnectingFaceUri(NEXTHOP2);
   nexthops2.setRouteCost(99);
   rte.getNexthopList().addNextHop(nexthops2);
 
   BOOST_CHECK_EQUAL(rte.getNexthopList().size(), 1);
   it =  rte.getNexthopList().begin();
-  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), "nexthop2");
+  BOOST_CHECK_EQUAL(it->getConnectingFaceUri(), NEXTHOP2);
   BOOST_CHECK_EQUAL(it->getRouteCost(), 99);
 }
 
 BOOST_AUTO_TEST_CASE(OutputStream)
 {
   RoutingTableEntry rte(ndn::Name("dest1"));
-
-  NextHop nexthops1;
-  nexthops1.setConnectingFaceUri("nexthop1");
-  nexthops1.setRouteCost(99);
-  rte.getNexthopList().addNextHop(nexthops1);
+  rte.getNexthopList().addNextHop({NEXTHOP1, 99});
 
   std::ostringstream os;
   os << rte;
 
   BOOST_CHECK_EQUAL(os.str(),
                     "  Destination: /dest1\n"
-                    "    NextHop(Uri: nexthop1, Cost: 99)\n");
+                    "    NextHop(Uri: udp4://192.168.3.1:6363, Cost: 99)\n");
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/route/test-routing-table-pool-entry.cpp b/tests/route/test-routing-table-pool-entry.cpp
index cf425d2..9b2be00 100644
--- a/tests/route/test-routing-table-pool-entry.cpp
+++ b/tests/route/test-routing-table-pool-entry.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2019,  The University of Memphis,
+/*
+ * Copyright (c) 2014-2023,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -35,11 +35,11 @@
 {
   NextHop hop1;
   hop1.setRouteCost(25);
-  hop1.setConnectingFaceUri("AAA");
+  hop1.setConnectingFaceUri(ndn::FaceUri("udp4://192.168.3.1:6363"));
 
   NextHop hop2;
   hop2.setRouteCost(10);
-  hop2.setConnectingFaceUri("BBB");
+  hop2.setConnectingFaceUri(ndn::FaceUri("udp4://192.168.3.2:6363"));
 
   NexthopList nhl1;
   NexthopList nhl2;
diff --git a/tests/route/test-routing-table.cpp b/tests/route/test-routing-table.cpp
index b777a04..a6ce36d 100644
--- a/tests/route/test-routing-table.cpp
+++ b/tests/route/test-routing-table.cpp
@@ -56,14 +56,18 @@
 
 const uint8_t RoutingTableData1[] = {
   // Header
-  0x90, 0x20,
+  0x90, 0x30,
   // Routing table entry
-  0x91, 0x1e,
+  0x91, 0x2e,
   // Destination
-  0x07, 0x07, 0x08, 0x05, 0x64, 0x65, 0x73, 0x74, 0x31, 0x8f, 0x13,
+  0x07, 0x07, 0x08, 0x05, 0x64, 0x65, 0x73, 0x74, 0x31,
   // Nexthop
-  0x8d, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x86, 0x08, 0x3f, 0xfa, 0x66,
-  0x66, 0x66, 0x66, 0x66, 0x66
+  0x8f, 0x23,
+  // Nexthop.Uri
+  0x8d, 0x17, 0x75, 0x64, 0x70, 0x34, 0x3a, 0x2f, 0x2f, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38,
+  0x2e, 0x33, 0x2e, 0x31, 0x3a, 0x36, 0x33, 0x36, 0x33,
+  // Nexthop.CostDouble
+  0x86, 0x08, 0x3f, 0xfa, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
 };
 
 const uint8_t RoutingTableData2[] = {
@@ -74,7 +78,7 @@
 BOOST_FIXTURE_TEST_CASE(Encode, RoutingTableFixture)
 {
   NextHop nexthops;
-  nexthops.setConnectingFaceUri("nexthop");
+  nexthops.setConnectingFaceUri(ndn::FaceUri("udp4://192.168.3.1:6363"));
   nexthops.setRouteCost(1.65);
   rt.addNextHop("dest1", nexthops);
   BOOST_TEST(rt.wireEncode() == RoutingTableData1, boost::test_tools::per_element());
@@ -94,7 +98,7 @@
   BOOST_CHECK_EQUAL(des1, "dest1");
 
   auto it2 = it1->getNexthopList().begin();
-  BOOST_CHECK_EQUAL(it2->getConnectingFaceUri(), "nexthop");
+  BOOST_CHECK_EQUAL(it2->getConnectingFaceUri(), ndn::FaceUri("udp4://192.168.3.1:6363"));
   BOOST_CHECK_EQUAL(it2->getRouteCost(), 1.65);
 
   BOOST_CHECK_EQUAL(rtStatus.m_rTable.size(), 1);
@@ -103,7 +107,7 @@
 BOOST_FIXTURE_TEST_CASE(OutputStream, RoutingTableFixture)
 {
   NextHop nexthops;
-  nexthops.setConnectingFaceUri("nexthop");
+  nexthops.setConnectingFaceUri(ndn::FaceUri("udp4://192.168.3.1:6363"));
   nexthops.setRouteCost(99);
   rt.addNextHop("dest1", nexthops);
 
@@ -113,7 +117,7 @@
   BOOST_CHECK_EQUAL(os.str(),
                     "Routing Table:\n"
                     "  Destination: /dest1\n"
-                    "    NextHop(Uri: nexthop, Cost: 99)\n");
+                    "    NextHop(Uri: udp4://192.168.3.1:6363, Cost: 99)\n");
 }
 
 BOOST_FIXTURE_TEST_CASE(UpdateFromLsdb, RoutingTableFixture)