interest: update ForwardingHint format

Recognize and encode ForwardingHint as a sequence of Names.
The previous format with Delegations is still accepted for decoding, but
Preference field is ignored and no sorting is performed.

Delegation and DelegationList classes have been deleted.

refs #5187

Change-Id: I6f6f94020657b65c3fccb501694416dda24b894b
diff --git a/tests/unit/delegation-list.t.cpp b/tests/unit/delegation-list.t.cpp
deleted file mode 100644
index 0831dca..0000000
--- a/tests/unit/delegation-list.t.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 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 "ndn-cxx/delegation-list.hpp"
-
-#include "tests/boost-test.hpp"
-#include <boost/lexical_cast.hpp>
-
-namespace ndn {
-namespace tests {
-
-BOOST_AUTO_TEST_SUITE(TestDelegationList)
-
-const uint8_t DEL1A[] = {
-  0x1f, 0x08, // Delegation
-        0x1e, 0x01, 0x01, // Preference=1
-        0x07, 0x03, 0x08, 0x01, 0x41 // Name=/A
-};
-const uint8_t DEL1B[] = {
-  0x1f, 0x08, // Delegation
-        0x1e, 0x01, 0x01, // Preference=1
-        0x07, 0x03, 0x08, 0x01, 0x42 // Name=/B
-};
-const uint8_t DEL2A[] = {
-  0x1f, 0x08, // Delegation
-        0x1e, 0x01, 0x02, // Preference=2
-        0x07, 0x03, 0x08, 0x01, 0x41 // Name=/A
-};
-const uint8_t DEL2B[] = {
-  0x1f, 0x08, // Delegation
-        0x1e, 0x01, 0x02, // Preference=2
-        0x07, 0x03, 0x08, 0x01, 0x42 // Name=/B
-};
-
-Block
-makeDelegationListBlock(uint32_t type, std::initializer_list<const uint8_t*> dels)
-{
-  Block block(type);
-  for (const uint8_t* del : dels) {
-    block.push_back(Block(del, 2 + del[1]));
-  }
-  block.encode();
-  return block;
-}
-
-BOOST_AUTO_TEST_SUITE(Decode)
-
-BOOST_AUTO_TEST_CASE(DecodeUnsorted)
-{
-  DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL2B, DEL1A}), false);
-  BOOST_CHECK_EQUAL(dl.size(), 3);
-  BOOST_CHECK_EQUAL(dl.at(0).preference, 2);
-  BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
-  BOOST_CHECK_EQUAL(dl.at(1).preference, 2);
-  BOOST_CHECK_EQUAL(dl.at(1).name, "/B");
-  BOOST_CHECK_EQUAL(dl.at(2).preference, 1);
-  BOOST_CHECK_EQUAL(dl.at(2).name, "/A");
-}
-
-BOOST_AUTO_TEST_CASE(DecodeSorted)
-{
-  DelegationList dl(makeDelegationListBlock(tlv::Content, {DEL2A, DEL2B, DEL1A}));
-  BOOST_CHECK_EQUAL(dl.size(), 3);
-  BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
-  BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
-  BOOST_CHECK_EQUAL(dl.at(1).preference, 2);
-  BOOST_CHECK_EQUAL(dl.at(1).name, "/A");
-  BOOST_CHECK_EQUAL(dl.at(2).preference, 2);
-  BOOST_CHECK_EQUAL(dl.at(2).name, "/B");
-}
-
-BOOST_AUTO_TEST_CASE(DecodeEmpty)
-{
-  DelegationList dl;
-  Block block = makeDelegationListBlock(tlv::ForwardingHint, {});
-  BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeBadType)
-{
-  DelegationList dl;
-  Block block = makeDelegationListBlock(tlv::Selectors, {DEL1A, DEL2B});
-  BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeNotDelegation)
-{
-  const uint8_t BAD_DEL[] = {
-    0x09, 0x00 // Selectors
-  };
-
-  DelegationList dl;
-  Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
-  BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeMissingPreference)
-{
-  const uint8_t BAD_DEL[] = {
-    0x1f, 0x05, // Delegation
-          0x07, 0x03, 0x08, 0x01, 0x42 // Name=/B
-  };
-
-  DelegationList dl;
-  Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
-  BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeMissingName)
-{
-  const uint8_t BAD_DEL[] = {
-    0x1f, 0x03, // Delegation
-          0x1e, 0x01, 0x02, // Preference=2
-  };
-
-  DelegationList dl;
-  Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
-  BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeUnknownField)
-{
-  const uint8_t BAD_DEL[] = {
-    0x1f, 0x0a, // Delegation
-          0x1e, 0x01, 0x02, // Preference=2
-          0x09, 0x00, // Selectors
-          0x07, 0x03, 0x08, 0x01, 0x42 // Name=/B
-  };
-
-  DelegationList dl;
-  Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
-  BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeWrongOrder)
-{
-  const uint8_t BAD_DEL[] = {
-    0x1f, 0x08, // Delegation
-          0x07, 0x03, 0x08, 0x01, 0x42, // Name=/B
-          0x1e, 0x01, 0x02 // Preference=2
-  };
-
-  DelegationList dl;
-  Block block = makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, BAD_DEL});
-  BOOST_CHECK_THROW(dl.wireDecode(block), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Decode
-
-BOOST_AUTO_TEST_SUITE(InsertEncode)
-
-BOOST_AUTO_TEST_CASE(InsertSimple)
-{
-  DelegationList dl;
-  BOOST_CHECK_EQUAL(dl.empty(), true);
-  dl.insert(2, "/A");
-  BOOST_CHECK_EQUAL(dl.empty(), false);
-  dl.insert(1, "/B");
-  BOOST_CHECK_EQUAL(dl.size(), 2);
-
-  EncodingBuffer encoder;
-  dl.wireEncode(encoder);
-  BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::ForwardingHint, {DEL1B, DEL2A}));
-}
-
-BOOST_AUTO_TEST_CASE(InsertReplace)
-{
-  DelegationList dl({{2, "/A"}});
-  dl.insert(Delegation{1, "/A"}, DelegationList::INS_REPLACE);
-  BOOST_CHECK_EQUAL(dl.size(), 1);
-  BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
-  BOOST_CHECK_EQUAL(dl[0].name, "/A");
-
-  EncodingBuffer encoder;
-  dl.wireEncode(encoder);
-  BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::ForwardingHint, {DEL1A}));
-}
-
-BOOST_AUTO_TEST_CASE(InsertAppend)
-{
-  DelegationList dl({{2, "/A"}});
-  dl.insert(Delegation{1, "/A"}, DelegationList::INS_APPEND);
-  BOOST_CHECK_EQUAL(dl.size(), 2);
-  BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
-  BOOST_CHECK_EQUAL(dl.at(1).preference, 2);
-
-  EncodingBuffer encoder;
-  dl.wireEncode(encoder);
-  BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::ForwardingHint, {DEL1A, DEL2A}));
-}
-
-BOOST_AUTO_TEST_CASE(InsertSkip)
-{
-  DelegationList dl({{2, "/A"}});
-  dl.insert(Delegation{1, "/A"}, DelegationList::INS_SKIP);
-  BOOST_CHECK_EQUAL(dl.size(), 1);
-  BOOST_CHECK_EQUAL(dl.at(0).preference, 2);
-
-  EncodingBuffer encoder;
-  dl.wireEncode(encoder);
-  BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::ForwardingHint, {DEL2A}));
-}
-
-BOOST_AUTO_TEST_CASE(Unsorted)
-{
-  DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A}), false);
-  dl.insert(1, "/B");
-  BOOST_CHECK_EQUAL(dl.size(), 2);
-  BOOST_CHECK_EQUAL(dl.at(0).preference, 2);
-  BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
-  BOOST_CHECK_EQUAL(dl.at(1).preference, 1);
-  BOOST_CHECK_EQUAL(dl.at(1).name, "/B");
-
-  EncodingBuffer encoder;
-  dl.wireEncode(encoder, tlv::Content);
-  BOOST_CHECK_EQUAL(encoder.block(), makeDelegationListBlock(tlv::Content, {DEL2A, DEL1B}));
-}
-
-BOOST_AUTO_TEST_CASE(EncodeBadType)
-{
-  DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A}));
-  EncodingBuffer encoder;
-  BOOST_CHECK_THROW(dl.wireEncode(encoder, tlv::Selectors), std::invalid_argument);
-}
-
-BOOST_AUTO_TEST_CASE(EncodeEmpty)
-{
-  DelegationList dl;
-  EncodingBuffer encoder;
-  BOOST_CHECK_THROW(dl.wireEncode(encoder), DelegationList::Error);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // InsertEncode
-
-BOOST_AUTO_TEST_SUITE(Erase)
-
-BOOST_AUTO_TEST_CASE(EraseNoop)
-{
-  DelegationList dl;
-  dl.insert(1, "/A");
-  BOOST_CHECK_EQUAL(dl.erase(2, "/A"), 0);
-  BOOST_CHECK_EQUAL(dl.erase(Delegation{1, "/B"}), 0);
-  BOOST_CHECK_EQUAL(dl.size(), 1);
-  BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
-  BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
-}
-
-BOOST_AUTO_TEST_CASE(EraseOne)
-{
-  DelegationList dl;
-  dl.insert(1, "/A");
-  BOOST_CHECK_EQUAL(dl.erase(1, "/A"), 1);
-  BOOST_CHECK_EQUAL(dl.size(), 0);
-}
-
-BOOST_AUTO_TEST_CASE(EraseByName)
-{
-  DelegationList dl;
-  dl.insert(1, "/A");
-  dl.insert(2, "/A", DelegationList::INS_APPEND);
-  BOOST_CHECK_EQUAL(dl.size(), 2);
-  BOOST_CHECK_EQUAL(dl.erase("/A"), 2);
-  BOOST_CHECK_EQUAL(dl.size(), 0);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Erase
-
-BOOST_AUTO_TEST_SUITE(Sort)
-
-BOOST_AUTO_TEST_CASE(Noop)
-{
-  DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL1A}));
-  BOOST_CHECK_EQUAL(dl.isSorted(), true);
-  dl.sort();
-  BOOST_CHECK_EQUAL(dl.isSorted(), true);
-}
-
-BOOST_AUTO_TEST_CASE(Sort)
-{
-  DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL2B, DEL1A}), false);
-  BOOST_CHECK_EQUAL(dl.isSorted(), false);
-  dl.sort();
-  BOOST_CHECK_EQUAL(dl.isSorted(), true);
-  BOOST_CHECK_EQUAL(dl.size(), 3);
-  BOOST_CHECK_EQUAL(dl.at(0).preference, 1);
-  BOOST_CHECK_EQUAL(dl.at(0).name, "/A");
-  BOOST_CHECK_EQUAL(dl.at(1).preference, 2);
-  BOOST_CHECK_EQUAL(dl.at(1).name, "/A");
-  BOOST_CHECK_EQUAL(dl.at(2).preference, 2);
-  BOOST_CHECK_EQUAL(dl.at(2).name, "/B");
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Sort
-
-BOOST_AUTO_TEST_SUITE(Compare)
-
-BOOST_AUTO_TEST_CASE(Empty)
-{
-  DelegationList dl1, dl2;
-  BOOST_CHECK_EQUAL(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_CASE(SortedEqual)
-{
-  DelegationList dl1(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B})),
-                 dl2(makeDelegationListBlock(tlv::Content, {DEL1B, DEL2A}));
-  BOOST_CHECK_EQUAL(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_CASE(SortedUnequal)
-{
-  DelegationList dl1(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B})),
-                 dl2(makeDelegationListBlock(tlv::Content, {DEL1A, DEL2B}));
-  BOOST_CHECK_NE(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_CASE(UnsortedSameOrder)
-{
-  DelegationList dl1(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B}), false),
-                 dl2(makeDelegationListBlock(tlv::Content, {DEL2A, DEL1B}), false);
-  BOOST_CHECK_EQUAL(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_CASE(UnsortedDifferentOrder)
-{
-  DelegationList dl1(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B}), false),
-                 dl2(makeDelegationListBlock(tlv::Content, {DEL1B, DEL2A}), false);
-  BOOST_CHECK_NE(dl1, dl2);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Compare
-
-BOOST_AUTO_TEST_SUITE(Print)
-
-BOOST_AUTO_TEST_CASE(PrintEmpty)
-{
-  DelegationList dl;
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(dl), "[]");
-}
-
-BOOST_AUTO_TEST_CASE(PrintNormal)
-{
-  DelegationList dl(makeDelegationListBlock(tlv::ForwardingHint, {DEL2A, DEL1B}));
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(dl), "[/B(1),/A(2)]");
-}
-
-BOOST_AUTO_TEST_SUITE_END() // Print
-
-BOOST_AUTO_TEST_SUITE_END() // TestDelegationList
-
-} // namespace tests
-} // namespace ndn
diff --git a/tests/unit/delegation.t.cpp b/tests/unit/delegation.t.cpp
deleted file mode 100644
index 9f23e89..0000000
--- a/tests/unit/delegation.t.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 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 "ndn-cxx/delegation.hpp"
-
-#include "tests/boost-test.hpp"
-#include <boost/lexical_cast.hpp>
-
-namespace ndn {
-namespace tests {
-
-BOOST_AUTO_TEST_SUITE(TestDelegation)
-
-BOOST_AUTO_TEST_CASE(Compare)
-{
-  BOOST_CHECK_EQUAL((Delegation{1, "/A"}), (Delegation{1, "/A"}));
-  BOOST_CHECK_LE((Delegation{1, "/A"}), (Delegation{1, "/A"}));
-  BOOST_CHECK_GE((Delegation{1, "/A"}), (Delegation{1, "/A"}));
-
-  BOOST_CHECK_NE((Delegation{1, "/A"}), (Delegation{2, "/A"}));
-  BOOST_CHECK_NE((Delegation{1, "/A"}), (Delegation{1, "/B"}));
-
-  BOOST_CHECK_LT((Delegation{1, "/A"}), (Delegation{1, "/B"}));
-  BOOST_CHECK_LE((Delegation{1, "/A"}), (Delegation{1, "/B"}));
-  BOOST_CHECK_LT((Delegation{1, "/B"}), (Delegation{2, "/A"}));
-  BOOST_CHECK_LE((Delegation{1, "/B"}), (Delegation{2, "/A"}));
-  BOOST_CHECK_LT((Delegation{1, "/A"}), (Delegation{2, "/A"}));
-  BOOST_CHECK_LE((Delegation{1, "/A"}), (Delegation{2, "/A"}));
-
-  BOOST_CHECK_GT((Delegation{1, "/B"}), (Delegation{1, "/A"}));
-  BOOST_CHECK_GE((Delegation{1, "/B"}), (Delegation{1, "/A"}));
-  BOOST_CHECK_GT((Delegation{2, "/A"}), (Delegation{1, "/B"}));
-  BOOST_CHECK_GE((Delegation{2, "/A"}), (Delegation{1, "/B"}));
-  BOOST_CHECK_GT((Delegation{2, "/A"}), (Delegation{1, "/A"}));
-  BOOST_CHECK_GE((Delegation{2, "/A"}), (Delegation{1, "/A"}));
-}
-
-BOOST_AUTO_TEST_CASE(Print)
-{
-  BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(Delegation{1, "/B"}), "/B(1)");
-}
-
-BOOST_AUTO_TEST_SUITE_END() // TestDelegation
-
-} // namespace tests
-} // namespace ndn
diff --git a/tests/unit/encoding/block-helpers.t.cpp b/tests/unit/encoding/block-helpers.t.cpp
index 4b26109..2ca1e02 100644
--- a/tests/unit/encoding/block-helpers.t.cpp
+++ b/tests/unit/encoding/block-helpers.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -134,6 +134,21 @@
   BOOST_CHECK_EQUAL(*b1.elements().begin(), name.wireEncode());
 }
 
+BOOST_AUTO_TEST_CASE(NestedSequence)
+{
+  std::vector<Name> names;
+  names.emplace_back("/A");
+  names.emplace_back("/B");
+  Block b1 = makeNestedBlock(100, names.begin(), names.end());
+
+  BOOST_CHECK_EQUAL(b1.type(), 100);
+  b1.parse();
+  auto elements = b1.elements();
+  BOOST_REQUIRE_EQUAL(elements.size(), 2);
+  BOOST_CHECK_EQUAL(Name(elements[0]), names[0]);
+  BOOST_CHECK_EQUAL(Name(elements[1]), names[1]);
+}
+
 BOOST_AUTO_TEST_SUITE_END() // TestBlockHelpers
 BOOST_AUTO_TEST_SUITE_END() // Encoding
 
diff --git a/tests/unit/interest.t.cpp b/tests/unit/interest.t.cpp
index b630e64..482eac8 100644
--- a/tests/unit/interest.t.cpp
+++ b/tests/unit/interest.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2021 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -153,7 +153,7 @@
 BOOST_AUTO_TEST_CASE(Full)
 {
   const uint8_t WIRE[] = {
-    0x05, 0x5c, // Interest
+    0x05, 0x56, // Interest
           0x07, 0x36, // Name
                 0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // GenericNameComponent
                 0x08, 0x03, 0x6e, 0x64, 0x6e, // GenericNameComponent
@@ -164,12 +164,8 @@
                       0xcc, 0xd7, 0x2c, 0x6e, 0xa0, 0xf7, 0x31, 0x5a,
           0x21, 0x00, // CanBePrefix
           0x12, 0x00, // MustBeFresh
-          0x1e, 0x0b, // ForwardingHint
-                0x1f, 0x09, // Delegation List
-                      0x1e, 0x02,
-                            0x3e, 0x15,
-                      0x07, 0x03,
-                            0x08, 0x01, 0x48,
+          0x1e, 0x05, // ForwardingHint
+                0x07, 0x03, 0x08, 0x01, 0x48,
           0x0a, 0x04, // Nonce
                 0x4c, 0x1e, 0xcb, 0x4a,
           0x0c, 0x02, // InterestLifetime
@@ -184,7 +180,7 @@
   i1.setName("/local/ndn/prefix");
   i1.setMustBeFresh(true);
   i1.setCanBePrefix(true);
-  i1.setForwardingHint(DelegationList({{15893, "/H"}}));
+  i1.setForwardingHint({"/H"});
   i1.setNonce(0x4c1ecb4a);
   i1.setInterestLifetime(30369_ms);
   i1.setHopLimit(220);
@@ -199,7 +195,7 @@
                     "/local/ndn/prefix/params-sha256=ff9100e04eaadcf30674d98026a051ba25f56b69bfa026dcccd72c6ea0f7315a");
   BOOST_CHECK_EQUAL(i2.getCanBePrefix(), true);
   BOOST_CHECK_EQUAL(i2.getMustBeFresh(), true);
-  BOOST_CHECK_EQUAL(i2.getForwardingHint(), DelegationList({{15893, "/H"}}));
+  BOOST_TEST(i2.getForwardingHint() == std::vector<Name>({"/H"}), boost::test_tools::per_element());
   BOOST_CHECK_EQUAL(i2.hasNonce(), true);
   BOOST_CHECK_EQUAL(i2.getNonce(), 0x4c1ecb4a);
   BOOST_CHECK_EQUAL(i2.getInterestLifetime(), 30369_ms);
@@ -385,7 +381,7 @@
   {
     // initialize all elements to non-empty, to verify wireDecode clears them
     i.setName("/A");
-    i.setForwardingHint({{10309, "/F"}});
+    i.setForwardingHint({"/F"});
     i.setNonce(0x03d645a8);
     i.setInterestLifetime(18554_ms);
     i.setHopLimit(64);
@@ -448,7 +444,7 @@
   BOOST_CHECK_EQUAL(i.getName(), "/I");
   BOOST_CHECK_EQUAL(i.getCanBePrefix(), true);
   BOOST_CHECK_EQUAL(i.getMustBeFresh(), true);
-  BOOST_CHECK_EQUAL(i.getForwardingHint(), DelegationList({{15893, "/H"}}));
+  BOOST_TEST(i.getForwardingHint() == std::vector<Name>({"/H"}), boost::test_tools::per_element());
   BOOST_CHECK_EQUAL(i.hasNonce(), true);
   BOOST_CHECK_EQUAL(i.getNonce(), 0x4acb1e4c);
   BOOST_CHECK_EQUAL(i.getInterestLifetime(), 30369_ms);
@@ -459,11 +455,13 @@
   // encode without modification: retain original wire encoding
   BOOST_CHECK_EQUAL(i.wireEncode().value_size(), 49);
 
-  // modify then re-encode: unrecognized elements are discarded
+  // modify then re-encode:
+  // * unrecognized elements are discarded;
+  // * ForwardingHint is re-encoded as a sequence of Names
   i.setName("/J");
   BOOST_CHECK_EQUAL(i.wireEncode(),
-                    "0523 0703(08014A) "
-                    "2100 1200 1E0B(1F09 1E023E15 0703080148) "
+                    "051D 0703(08014A) "
+                    "2100 1200 1E05(0703080148) "
                     "0A044ACB1E4C 0C0276A1 2201D6"_block);
 }
 
@@ -476,7 +474,7 @@
                     "/I/params-sha256=f16db273f40436a852063f864d5072b01ead53151f5a688ea1560492bebedd05");
   BOOST_CHECK_EQUAL(i.getCanBePrefix(), true);
   BOOST_CHECK_EQUAL(i.getMustBeFresh(), true);
-  BOOST_CHECK_EQUAL(i.getForwardingHint(), DelegationList({{15893, "/H"}}));
+  BOOST_TEST(i.getForwardingHint() == std::vector<Name>({"/H"}), boost::test_tools::per_element());
   BOOST_CHECK_EQUAL(i.hasNonce(), true);
   BOOST_CHECK_EQUAL(i.getNonce(), 0x4acb1e4c);
   BOOST_CHECK_EQUAL(i.getInterestLifetime(), 30369_ms);
@@ -487,21 +485,22 @@
   // encode without modification: retain original wire encoding
   BOOST_CHECK_EQUAL(i.wireEncode().value_size(), 91);
 
-  // modify then re-encode: unrecognized elements after ApplicationParameters
-  //                        are preserved, the rest are discarded
+  // modify then re-encode:
+  // * unrecognized elements after ApplicationParameters are preserved, the rest are discarded;
+  // * ForwardingHint is re-encoded as a sequence of Names
   i.setName("/J");
   BOOST_CHECK_EQUAL(i.isParametersDigestValid(), true);
   BOOST_CHECK_EQUAL(i.wireEncode(),
-                    "054D 0725(08014A 0220F16DB273F40436A852063F864D5072B01EAD53151F5A688EA1560492BEBEDD05) "
-                    "2100 1200 1E0B(1F09 1E023E15 0703080148) "
+                    "0547 0725(08014A 0220F16DB273F40436A852063F864D5072B01EAD53151F5A688EA1560492BEBEDD05) "
+                    "2100 1200 1E05(0703080148) "
                     "0A044ACB1E4C 0C0276A1 2201D6 2404C0C1C2C3 FC00"_block);
 
   // modify ApplicationParameters: unrecognized elements are preserved
   i.setApplicationParameters("2402CAFE"_block);
   BOOST_CHECK_EQUAL(i.isParametersDigestValid(), true);
   BOOST_CHECK_EQUAL(i.wireEncode(),
-                    "054B 0725(08014A 02205FDA67967EE302FC457E41B7D3D51BA6A9379574D193FD88F64954BF16C2927A) "
-                    "2100 1200 1E0B(1F09 1E023E15 0703080148) "
+                    "0545 0725(08014A 02205FDA67967EE302FC457E41B7D3D51BA6A9379574D193FD88F64954BF16C2927A) "
+                    "2100 1200 1E05(0703080148) "
                     "0A044ACB1E4C 0C0276A1 2201D6 2402CAFE FC00"_block);
 }
 
@@ -689,7 +688,7 @@
   interest.setName("/A")
           .setCanBePrefix(true)
           .setMustBeFresh(true)
-          .setForwardingHint({{1, "/H"}})
+          .setForwardingHint({"/H"})
           .setNonce(2228)
           .setInterestLifetime(5_s)
           .setHopLimit(90);
@@ -706,7 +705,8 @@
   other.setMustBeFresh(interest.getMustBeFresh());
   BOOST_CHECK_EQUAL(interest.matchesInterest(other), false); // will match until #3162 implemented
 
-  other.setForwardingHint(interest.getForwardingHint());
+  auto fh = interest.getForwardingHint();
+  other.setForwardingHint(std::vector<Name>(fh.begin(), fh.end()));
   BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
 
   other.setNonce(9336);
@@ -754,19 +754,6 @@
   BOOST_CHECK_EQUAL(i.getMustBeFresh(), false);
 }
 
-BOOST_AUTO_TEST_CASE(ModifyForwardingHint)
-{
-  Interest i("/I");
-  i.setCanBePrefix(false);
-  i.setForwardingHint({{1, "/A"}});
-  i.wireEncode();
-  BOOST_CHECK(i.hasWire());
-
-  i.modifyForwardingHint([] (DelegationList& fh) { fh.insert(2, "/B"); });
-  BOOST_CHECK(!i.hasWire());
-  BOOST_CHECK_EQUAL(i.getForwardingHint(), DelegationList({{1, "/A"}, {2, "/B"}}));
-}
-
 BOOST_AUTO_TEST_CASE(GetNonce)
 {
   unique_ptr<Interest> i1, i2;
diff --git a/tests/unit/link.t.cpp b/tests/unit/link.t.cpp
index 1042d35..2d7fa9c 100644
--- a/tests/unit/link.t.cpp
+++ b/tests/unit/link.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2020 Regents of the University of California.
+ * Copyright (c) 2013-2022 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
  *
@@ -29,7 +29,7 @@
 BOOST_AUTO_TEST_SUITE(TestLink)
 
 const uint8_t GOOD_LINK[] = {
-0x06, 0xda, // Data
+0x06, 0xd0, // Data
     0x07, 0x14, // Name
         0x08, 0x05,
             0x6c, 0x6f, 0x63, 0x61, 0x6c,
@@ -42,19 +42,13 @@
             0x01,
         0x19, 0x02, // FreshnessPeriod
             0x27, 0x10,
-    0x15, 0x1a, // Content
-        0x1f, 0x0c, // LinkDelegation
-            0x1e, 0x01, // LinkPreference
-                0x0a,
-            0x07, 0x07, // Name
-                0x08, 0x05,
-                    0x6c, 0x6f, 0x63, 0x61, 0x6c,
-        0x1f, 0x0a, // LinkDelegation
-            0x1e, 0x01, // LinkPreference
-                0x14,
-            0x07, 0x05, // Name
-                0x08, 0x03,
-                    0x6e, 0x64, 0x6e,
+    0x15, 0x10, // Content
+        0x07, 0x07, // Name
+            0x08, 0x05,
+                0x6c, 0x6f, 0x63, 0x61, 0x6c,
+        0x07, 0x05, // Name
+            0x08, 0x03,
+                0x6e, 0x64, 0x6e,
     0x16, 0x1b, // SignatureInfo
         0x1b, 0x01, // SignatureType
             0x01,
@@ -85,8 +79,8 @@
 {
   Link link(Block(GOOD_LINK, sizeof(GOOD_LINK)));
   BOOST_CHECK_EQUAL(link.getName(), Name("/local/ndn/prefix"));
-  BOOST_CHECK_EQUAL(link.getDelegationList(),
-                    DelegationList({{10, Name("/local")}, {20, Name("/ndn")}}));
+  BOOST_TEST(link.getDelegationList() == std::vector<Name>({"/local", "/ndn"}),
+             boost::test_tools::per_element());
 }
 
 BOOST_AUTO_TEST_CASE(DecodeBadContentType)
@@ -102,14 +96,14 @@
 
 BOOST_AUTO_TEST_CASE(Encode)
 {
-  Link link1("/test", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}});
+  Link link1("/test", {"/test1", "/test2", "/test3"});
   signData(link1);
   Block wire = link1.wireEncode();
 
   Link link2(wire);
   BOOST_CHECK_EQUAL(link2.getName(), "/test");
-  BOOST_CHECK_EQUAL(link2.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}));
+  BOOST_TEST(link2.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3"}),
+             boost::test_tools::per_element());
 }
 
 BOOST_AUTO_TEST_SUITE_END() // EncodeDecode
@@ -119,54 +113,55 @@
 BOOST_AUTO_TEST_CASE(SetDelegationList)
 {
   Link link("/test");
-  BOOST_CHECK_EQUAL(link.getDelegationList(), DelegationList());
+  BOOST_CHECK(link.getDelegationList().empty());
 
-  link.setDelegationList(DelegationList({{10, "/test1"}, {20, "/test2"}}));
-  BOOST_CHECK_EQUAL(link.getDelegationList(), DelegationList({{10, "/test1"}, {20, "/test2"}}));
+  link.setDelegationList(std::vector<Name>({"/test1", "/test2"}));
+  BOOST_TEST(link.getDelegationList() == std::vector<Name>({"/test1", "/test2"}),
+             boost::test_tools::per_element());
 }
 
 BOOST_AUTO_TEST_CASE(AddDelegation)
 {
-  Link link1("/test", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}});
-  BOOST_CHECK_EQUAL(link1.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}));
+  Link link1("/test", {"/test1", "/test2", "/test3"});
+  BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3"}),
+             boost::test_tools::per_element());
 
-  link1.addDelegation(30, "/test4");
-  BOOST_CHECK_EQUAL(link1.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {20, "/test2"}, {30, "/test4"}, {100, "/test3"}}));
+  BOOST_CHECK(link1.addDelegation("/test4"));
+  BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3", "/test4"}),
+             boost::test_tools::per_element());
 
-  link1.addDelegation(40, "/test2");
-  BOOST_CHECK_EQUAL(link1.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {30, "/test4"}, {40, "/test2"}, {100, "/test3"}}));
+  BOOST_CHECK(!link1.addDelegation("/test2"));
+  BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3", "/test4"}),
+             boost::test_tools::per_element());
 
   signData(link1);
   Link link2(link1.wireEncode());
-  BOOST_CHECK_EQUAL(link2.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {30, "/test4"}, {40, "/test2"}, {100, "/test3"}}));
+  BOOST_TEST(link2.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3", "/test4"}),
+             boost::test_tools::per_element());
 }
 
 BOOST_AUTO_TEST_CASE(RemoveDelegation)
 {
-  Link link1("/test", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}});
-  BOOST_CHECK_EQUAL(link1.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}));
+  Link link1("/test", {"/test1", "/test2", "/test3"});
+  BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3"}),
+             boost::test_tools::per_element());
 
-  link1.removeDelegation("/test4"); // non-existent
-  BOOST_CHECK_EQUAL(link1.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {20, "/test2"}, {100, "/test3"}}));
+  BOOST_CHECK(!link1.removeDelegation("/test4")); // non-existent
+  BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test2", "/test3"}),
+             boost::test_tools::per_element());
 
-  link1.removeDelegation("/test2");
-  BOOST_CHECK_EQUAL(link1.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {100, "/test3"}}));
+  BOOST_CHECK(link1.removeDelegation("/test2"));
+  BOOST_TEST(link1.getDelegationList() == std::vector<Name>({"/test1", "/test3"}),
+             boost::test_tools::per_element());
 
   signData(link1);
   Link link2(link1.wireEncode());
-  BOOST_CHECK_EQUAL(link2.getDelegationList(),
-                    DelegationList({{10, "/test1"}, {100, "/test3"}}));
+  BOOST_TEST(link2.getDelegationList() == std::vector<Name>({"/test1", "/test3"}),
+             boost::test_tools::per_element());
 
   link1.removeDelegation("/test1");
   link1.removeDelegation("/test3");
-  BOOST_CHECK_EQUAL(link1.getDelegationList(), DelegationList());
+  BOOST_CHECK(link1.getDelegationList().empty());
 }
 
 BOOST_AUTO_TEST_SUITE_END() // Modify