interest: reorganize code and test cases

* Sort functions to generally follow the order of fields in wire format.
* Merge similar constructors.
* Sort tests to follow the code order.
* Split InterestFilter to its own test suite.
* Add test coverage for Interest::getNonce() and
  Interest::refreshNonce().
* Move Link and SelectedDelegation tests to a sub test suite.
* Delete tests of malformed Link, which are already covered by
  Link test suite.

refs #4171

Change-Id: Ia7115f0be479e301673897115d112b0544a47f9e
diff --git a/src/interest.cpp b/src/interest.cpp
index 8959881..34ebd4a 100644
--- a/src/interest.cpp
+++ b/src/interest.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -35,24 +35,14 @@
 static_assert(std::is_base_of<tlv::Error, Interest::Error>::value,
               "Interest::Error must inherit from tlv::Error");
 
-Interest::Interest()
-  : m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
-  , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
-{
-}
-
-Interest::Interest(const Name& name)
-  : m_name(name)
-  , m_interestLifetime(DEFAULT_INTEREST_LIFETIME)
-  , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
-{
-}
-
-Interest::Interest(const Name& name, const time::milliseconds& interestLifetime)
+Interest::Interest(const Name& name, time::milliseconds interestLifetime)
   : m_name(name)
   , m_interestLifetime(interestLifetime)
   , m_selectedDelegationIndex(INVALID_SELECTED_DELEGATION_INDEX)
 {
+  if (interestLifetime < time::milliseconds::zero()) {
+    BOOST_THROW_EXCEPTION(std::invalid_argument("InterestLifetime must be >= 0"));
+  }
 }
 
 Interest::Interest(const Block& wire)
@@ -60,49 +50,148 @@
   wireDecode(wire);
 }
 
-uint32_t
-Interest::getNonce() const
-{
-  if (!m_nonce.hasWire())
-    const_cast<Interest*>(this)->setNonce(random::generateWord32());
+// ---- encode and decode ----
 
-  if (m_nonce.value_size() == sizeof(uint32_t))
-    return *reinterpret_cast<const uint32_t*>(m_nonce.value());
-  else {
-    // for compatibility reasons.  Should be removed eventually
-    return readNonNegativeInteger(m_nonce);
+template<encoding::Tag TAG>
+size_t
+Interest::wireEncode(EncodingImpl<TAG>& encoder) const
+{
+  size_t totalLength = 0;
+
+  // Interest ::= INTEREST-TYPE TLV-LENGTH
+  //                Name
+  //                Selectors?
+  //                Nonce
+  //                InterestLifetime?
+  //                Link?
+  //                SelectedDelegation?
+
+  // (reverse encoding)
+
+  // Link and SelectedDelegation
+  if (hasLink()) {
+    if (hasSelectedDelegation()) {
+      totalLength += prependNonNegativeIntegerBlock(encoder,
+                                                    tlv::SelectedDelegation,
+                                                    m_selectedDelegationIndex);
+    }
+    totalLength += encoder.prependBlock(m_link);
   }
+  else {
+    BOOST_ASSERT(!hasSelectedDelegation());
+  }
+
+  // InterestLifetime
+  if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
+    totalLength += prependNonNegativeIntegerBlock(encoder,
+                                                  tlv::InterestLifetime,
+                                                  getInterestLifetime().count());
+  }
+
+  // Nonce
+  getNonce(); // to ensure that Nonce is properly set
+  totalLength += encoder.prependBlock(m_nonce);
+
+  // Selectors
+  if (hasSelectors()) {
+    totalLength += getSelectors().wireEncode(encoder);
+  }
+
+  // Name
+  totalLength += getName().wireEncode(encoder);
+
+  totalLength += encoder.prependVarNumber(totalLength);
+  totalLength += encoder.prependVarNumber(tlv::Interest);
+  return totalLength;
 }
 
-Interest&
-Interest::setNonce(uint32_t nonce)
+template size_t
+Interest::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
+
+template size_t
+Interest::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
+
+const Block&
+Interest::wireEncode() const
 {
-  if (m_wire.hasWire() && m_nonce.value_size() == sizeof(uint32_t)) {
-    std::memcpy(const_cast<uint8_t*>(m_nonce.value()), &nonce, sizeof(nonce));
-  }
-  else {
-    m_nonce = makeBinaryBlock(tlv::Nonce,
-                              reinterpret_cast<const uint8_t*>(&nonce),
-                              sizeof(nonce));
-    m_wire.reset();
-  }
-  return *this;
+  if (m_wire.hasWire())
+    return m_wire;
+
+  EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  // to ensure that Nonce block points to the right memory location
+  const_cast<Interest*>(this)->wireDecode(buffer.block());
+
+  return m_wire;
 }
 
 void
-Interest::refreshNonce()
+Interest::wireDecode(const Block& wire)
 {
-  if (!hasNonce())
-    return;
+  m_wire = wire;
+  m_wire.parse();
 
-  uint32_t oldNonce = getNonce();
-  uint32_t newNonce = oldNonce;
-  while (newNonce == oldNonce)
-    newNonce = random::generateWord32();
+  if (m_wire.type() != tlv::Interest)
+    BOOST_THROW_EXCEPTION(Error("Unexpected TLV number when decoding Interest"));
 
-  setNonce(newNonce);
+  // Name
+  m_name.wireDecode(m_wire.get(tlv::Name));
+
+  // Selectors
+  Block::element_const_iterator val = m_wire.find(tlv::Selectors);
+  if (val != m_wire.elements_end()) {
+    m_selectors.wireDecode(*val);
+  }
+  else
+    m_selectors = Selectors();
+
+  // Nonce
+  m_nonce = m_wire.get(tlv::Nonce);
+
+  // InterestLifetime
+  val = m_wire.find(tlv::InterestLifetime);
+  if (val != m_wire.elements_end()) {
+    m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
+  }
+  else {
+    m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
+  }
+
+  // Link
+  m_linkCached.reset();
+  val = m_wire.find(tlv::Data);
+  if (val != m_wire.elements_end()) {
+    m_link = (*val);
+  }
+  else {
+    m_link = Block();
+  }
+
+  // SelectedDelegation
+  val = m_wire.find(tlv::SelectedDelegation);
+  if (val != m_wire.elements_end()) {
+    if (!this->hasLink()) {
+      BOOST_THROW_EXCEPTION(Error("Interest contains SelectedDelegation, but no LINK object"));
+    }
+    uint64_t selectedDelegation = readNonNegativeInteger(*val);
+    if (selectedDelegation < uint64_t(Link::countDelegationsFromWire(m_link))) {
+      m_selectedDelegationIndex = static_cast<size_t>(selectedDelegation);
+    }
+    else {
+      BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index when decoding Interest"));
+    }
+  }
+  else {
+    m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
+  }
 }
 
+// ---- matching ----
+
 bool
 Interest::matchesName(const Name& name) const
 {
@@ -222,6 +311,51 @@
           this->getSelectors() == other.getSelectors());
 }
 
+// ---- field accessors ----
+
+uint32_t
+Interest::getNonce() const
+{
+  if (!m_nonce.hasWire())
+    const_cast<Interest*>(this)->setNonce(random::generateWord32());
+
+  if (m_nonce.value_size() == sizeof(uint32_t))
+    return *reinterpret_cast<const uint32_t*>(m_nonce.value());
+  else {
+    // for compatibility reasons.  Should be removed eventually
+    return readNonNegativeInteger(m_nonce);
+  }
+}
+
+Interest&
+Interest::setNonce(uint32_t nonce)
+{
+  if (m_wire.hasWire() && m_nonce.value_size() == sizeof(uint32_t)) {
+    std::memcpy(const_cast<uint8_t*>(m_nonce.value()), &nonce, sizeof(nonce));
+  }
+  else {
+    m_nonce = makeBinaryBlock(tlv::Nonce,
+                              reinterpret_cast<const uint8_t*>(&nonce),
+                              sizeof(nonce));
+    m_wire.reset();
+  }
+  return *this;
+}
+
+void
+Interest::refreshNonce()
+{
+  if (!hasNonce())
+    return;
+
+  uint32_t oldNonce = getNonce();
+  uint32_t newNonce = oldNonce;
+  while (newNonce == oldNonce)
+    newNonce = random::generateWord32();
+
+  setNonce(newNonce);
+}
+
 Interest&
 Interest::setInterestLifetime(time::milliseconds interestLifetime)
 {
@@ -233,151 +367,6 @@
   return *this;
 }
 
-template<encoding::Tag TAG>
-size_t
-Interest::wireEncode(EncodingImpl<TAG>& encoder) const
-{
-  size_t totalLength = 0;
-
-  // Interest ::= INTEREST-TYPE TLV-LENGTH
-  //                Name
-  //                Selectors?
-  //                Nonce
-  //                InterestLifetime?
-  //                Link?
-  //                SelectedDelegation?
-
-  // (reverse encoding)
-
-  if (hasLink()) {
-    if (hasSelectedDelegation()) {
-      totalLength += prependNonNegativeIntegerBlock(encoder,
-                                                    tlv::SelectedDelegation,
-                                                    m_selectedDelegationIndex);
-    }
-    totalLength += encoder.prependBlock(m_link);
-  }
-  else {
-    BOOST_ASSERT(!hasSelectedDelegation());
-  }
-
-  // InterestLifetime
-  if (getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
-    totalLength += prependNonNegativeIntegerBlock(encoder,
-                                                  tlv::InterestLifetime,
-                                                  getInterestLifetime().count());
-  }
-
-  // Nonce
-  getNonce(); // to ensure that Nonce is properly set
-  totalLength += encoder.prependBlock(m_nonce);
-
-  // Selectors
-  if (hasSelectors()) {
-    totalLength += getSelectors().wireEncode(encoder);
-  }
-
-  // Name
-  totalLength += getName().wireEncode(encoder);
-
-  totalLength += encoder.prependVarNumber(totalLength);
-  totalLength += encoder.prependVarNumber(tlv::Interest);
-  return totalLength;
-}
-
-template size_t
-Interest::wireEncode<encoding::EncoderTag>(EncodingImpl<encoding::EncoderTag>& encoder) const;
-
-template size_t
-Interest::wireEncode<encoding::EstimatorTag>(EncodingImpl<encoding::EstimatorTag>& encoder) const;
-
-const Block&
-Interest::wireEncode() const
-{
-  if (m_wire.hasWire())
-    return m_wire;
-
-  EncodingEstimator estimator;
-  size_t estimatedSize = wireEncode(estimator);
-
-  EncodingBuffer buffer(estimatedSize, 0);
-  wireEncode(buffer);
-
-  // to ensure that Nonce block points to the right memory location
-  const_cast<Interest*>(this)->wireDecode(buffer.block());
-
-  return m_wire;
-}
-
-void
-Interest::wireDecode(const Block& wire)
-{
-  m_wire = wire;
-  m_wire.parse();
-
-  // Interest ::= INTEREST-TYPE TLV-LENGTH
-  //                Name
-  //                Selectors?
-  //                Nonce
-  //                InterestLifetime?
-  //                Link?
-  //                SelectedDelegation?
-
-  if (m_wire.type() != tlv::Interest)
-    BOOST_THROW_EXCEPTION(Error("Unexpected TLV number when decoding Interest"));
-
-  // Name
-  m_name.wireDecode(m_wire.get(tlv::Name));
-
-  // Selectors
-  Block::element_const_iterator val = m_wire.find(tlv::Selectors);
-  if (val != m_wire.elements_end()) {
-    m_selectors.wireDecode(*val);
-  }
-  else
-    m_selectors = Selectors();
-
-  // Nonce
-  m_nonce = m_wire.get(tlv::Nonce);
-
-  // InterestLifetime
-  val = m_wire.find(tlv::InterestLifetime);
-  if (val != m_wire.elements_end()) {
-    m_interestLifetime = time::milliseconds(readNonNegativeInteger(*val));
-  }
-  else {
-    m_interestLifetime = DEFAULT_INTEREST_LIFETIME;
-  }
-
-  // Link object
-  m_linkCached.reset();
-  val = m_wire.find(tlv::Data);
-  if (val != m_wire.elements_end()) {
-    m_link = (*val);
-  }
-  else {
-    m_link = Block();
-  }
-
-  // SelectedDelegation
-  val = m_wire.find(tlv::SelectedDelegation);
-  if (val != m_wire.elements_end()) {
-    if (!this->hasLink()) {
-      BOOST_THROW_EXCEPTION(Error("Interest contains SelectedDelegation, but no LINK object"));
-    }
-    uint64_t selectedDelegation = readNonNegativeInteger(*val);
-    if (selectedDelegation < uint64_t(Link::countDelegationsFromWire(m_link))) {
-      m_selectedDelegationIndex = static_cast<size_t>(selectedDelegation);
-    }
-    else {
-      BOOST_THROW_EXCEPTION(Error("Invalid selected delegation index when decoding Interest"));
-    }
-  }
-  else {
-    m_selectedDelegationIndex = INVALID_SELECTED_DELEGATION_INDEX;
-  }
-}
-
 bool
 Interest::hasLink() const
 {
@@ -462,6 +451,8 @@
   m_wire.reset();
 }
 
+// ---- operators ----
+
 std::ostream&
 operator<<(std::ostream& os, const Interest& interest)
 {
diff --git a/src/interest.hpp b/src/interest.hpp
index 78e6802..e9af4cf 100644
--- a/src/interest.hpp
+++ b/src/interest.hpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -22,11 +22,11 @@
 #ifndef NDN_INTEREST_HPP
 #define NDN_INTEREST_HPP
 
+#include "link.hpp"
 #include "name.hpp"
 #include "selectors.hpp"
-#include "util/time.hpp"
 #include "tag-host.hpp"
-#include "link.hpp"
+#include "util/time.hpp"
 
 namespace ndn {
 
@@ -52,31 +52,17 @@
     }
   };
 
-  /** @brief Create a new Interest with an empty name (`ndn:/`)
-   *  @warning In certain contexts that use Interest::shared_from_this(), Interest must be created
-   *           using `make_shared`. Otherwise, .shared_from_this() will throw an exception.
-   */
-  Interest();
-
-  /** @brief Create a new Interest with the given name
-   *  @param name The name for the interest.
-   *  @note This constructor allows implicit conversion from Name.
-   *  @warning In certain contexts that use Interest::shared_from_this(), Interest must be created
-   *           using `make_shared`. Otherwise, .shared_from_this() will throw an exception.
-   */
-  Interest(const Name& name);
-
   /** @brief Create a new Interest with the given name and interest lifetime
-   *  @param name             The name for the interest.
-   *  @param interestLifetime The interest lifetime in time::milliseconds, or -1 for none.
+   *  @note This constructor allows implicit conversion from Name.
+   *  @throw std::invalid_argument InterestLifetime is negative
    *  @warning In certain contexts that use Interest::shared_from_this(), Interest must be created
-   *           using `make_shared`. Otherwise, .shared_from_this() will throw an exception.
+   *           using `make_shared`. Otherwise, .shared_from_this() will trigger undefined behavior.
    */
-  Interest(const Name& name, const time::milliseconds& interestLifetime);
+  Interest(const Name& name = Name(), time::milliseconds interestLifetime = DEFAULT_INTEREST_LIFETIME);
 
   /** @brief Create from wire encoding
    *  @warning In certain contexts that use Interest::shared_from_this(), Interest must be created
-   *           using `make_shared`. Otherwise, .shared_from_this() will throw an exception.
+   *           using `make_shared`. Otherwise, .shared_from_this() will trigger undefined behavior.
    */
   explicit
   Interest(const Block& wire);
@@ -118,77 +104,6 @@
   std::string
   toUri() const;
 
-public: // Link and forwarding hint
-  /**
-   * @brief Check whether the Interest contains a Link object
-   * @return True if there is a link object, otherwise false
-   */
-  bool
-  hasLink() const;
-
-  /**
-   * @brief Get the link object for this interest
-   * @return The link object if there is one contained in this interest
-   * @throws Interest::Error if there is no link object contained in the interest
-   * @throws tlv::Error if the incorporated link object is malformed
-   */
-  const Link&
-  getLink() const;
-
-  /**
-   * @brief Set the link object for this interest
-   * @param link The link object that will be included in this interest (in wire format)
-   * @post !hasSelectedDelegation()
-   */
-  void
-  setLink(const Block& link);
-
-  /**
-   * @brief Delete the link object for this interest
-   * @post !hasLink()
-   */
-  void
-  unsetLink();
-
-  /**
-   * @brief Check whether the Interest includes a selected delegation
-   * @return True if there is a selected delegation, otherwise false
-   */
-  bool
-  hasSelectedDelegation() const;
-
-  /**
-   * @brief Get the name of the selected delegation
-   * @return The name of the selected delegation
-   * @throw Error SelectedDelegation is not set.
-   */
-  Name
-  getSelectedDelegation() const;
-
-  /**
-   * @brief Set the selected delegation
-   * @param delegationName The name of the selected delegation
-   * @throw Error Link is not set.
-   * @throw std::invalid_argument @p delegationName does not exist in Link.
-   */
-  void
-  setSelectedDelegation(const Name& delegationName);
-
-  /**
-   * @brief Set the selected delegation
-   * @param delegationIndex The index of the selected delegation
-   * @throw Error Link is not set.
-   * @throw std::out_of_range @p delegationIndex is out of bound in Link.
-   */
-  void
-  setSelectedDelegation(size_t delegationIndex);
-
-   /**
-   * @brief Unset the selected delegation
-   */
-  void
-  unsetSelectedDelegation();
-
 public: // matching
   /** @brief Check if Interest, including selectors, matches the given @p name
    *  @param name The name to be matched. If this is a Data name, it shall contain the
@@ -219,7 +134,7 @@
   bool
   matchesInterest(const Interest& other) const;
 
-public: // Name and guiders
+public: // Name, Nonce, and Guiders
   const Name&
   getName() const
   {
@@ -234,19 +149,6 @@
     return *this;
   }
 
-  const time::milliseconds&
-  getInterestLifetime() const
-  {
-    return m_interestLifetime;
-  }
-
-  /**
-   * @brief Set Interest's lifetime
-   * @throw std::invalid_argument specified lifetime is < 0
-   */
-  Interest&
-  setInterestLifetime(time::milliseconds interestLifetime);
-
   /** @brief Check if Nonce set
    */
   bool
@@ -280,6 +182,19 @@
   void
   refreshNonce();
 
+  time::milliseconds
+  getInterestLifetime() const
+  {
+    return m_interestLifetime;
+  }
+
+  /**
+   * @brief Set Interest's lifetime
+   * @throw std::invalid_argument specified lifetime is < 0
+   */
+  Interest&
+  setInterestLifetime(time::milliseconds interestLifetime);
+
 public: // Selectors
   /**
    * @return true if Interest has any selector present
@@ -388,18 +303,76 @@
     return *this;
   }
 
-public: // EqualityComparable concept
+public: // Link and SelectedDelegation
+  /**
+   * @brief Check whether the Interest contains a Link object
+   * @return True if there is a link object, otherwise false
+   */
   bool
-  operator==(const Interest& other) const
-  {
-    return wireEncode() == other.wireEncode();
-  }
+  hasLink() const;
 
+  /**
+   * @brief Get the link object for this interest
+   * @return The link object if there is one contained in this interest
+   * @throws Interest::Error if there is no link object contained in the interest
+   * @throws tlv::Error if the incorporated link object is malformed
+   */
+  const Link&
+  getLink() const;
+
+  /**
+   * @brief Set the link object for this interest
+   * @param link The link object that will be included in this interest (in wire format)
+   * @post !hasSelectedDelegation()
+   */
+  void
+  setLink(const Block& link);
+
+  /**
+   * @brief Delete the link object for this interest
+   * @post !hasLink()
+   */
+  void
+  unsetLink();
+
+  /**
+   * @brief Check whether the Interest includes a selected delegation
+   * @return True if there is a selected delegation, otherwise false
+   */
   bool
-  operator!=(const Interest& other) const
-  {
-    return !(*this == other);
-  }
+  hasSelectedDelegation() const;
+
+  /**
+   * @brief Get the name of the selected delegation
+   * @return The name of the selected delegation
+   * @throw Error SelectedDelegation is not set.
+   */
+  Name
+  getSelectedDelegation() const;
+
+  /**
+   * @brief Set the selected delegation
+   * @param delegationName The name of the selected delegation
+   * @throw Error Link is not set.
+   * @throw std::invalid_argument @p delegationName does not exist in Link.
+   */
+  void
+  setSelectedDelegation(const Name& delegationName);
+
+  /**
+   * @brief Set the selected delegation
+   * @param delegationIndex The index of the selected delegation
+   * @throw Error Link is not set.
+   * @throw std::out_of_range @p delegationIndex is out of bound in Link.
+   */
+  void
+  setSelectedDelegation(size_t delegationIndex);
+
+  /**
+   * @brief Unset the selected delegation
+   */
+  void
+  unsetSelectedDelegation();
 
 private:
   Name m_name;
@@ -424,6 +397,18 @@
   return os.str();
 }
 
+inline bool
+operator==(const Interest& lhs, const Interest& rhs)
+{
+  return lhs.wireEncode() == rhs.wireEncode();
+}
+
+inline bool
+operator!=(const Interest& lhs, const Interest& rhs)
+{
+  return !(lhs == rhs);
+}
+
 } // namespace ndn
 
 #endif // NDN_INTEREST_HPP
diff --git a/tests/unit-tests/interest-filter.t.cpp b/tests/unit-tests/interest-filter.t.cpp
new file mode 100644
index 0000000..e39f8dd
--- /dev/null
+++ b/tests/unit-tests/interest-filter.t.cpp
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2017 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 "interest-filter.hpp"
+#include "data.hpp"
+#include "security/signature-sha256-with-rsa.hpp"
+#include "security/digest-sha256.hpp"
+#include "encoding/buffer-stream.hpp"
+
+#include "boost-test.hpp"
+#include "identity-management-fixture.hpp"
+
+namespace ndn {
+namespace tests {
+
+BOOST_AUTO_TEST_SUITE(TestInterestFilter)
+
+BOOST_AUTO_TEST_CASE(Matching)
+{
+  BOOST_CHECK_EQUAL(InterestFilter("/a").doesMatch("/a/b"), true);
+  BOOST_CHECK_EQUAL(InterestFilter("/a/b").doesMatch("/a/b"), true);
+  BOOST_CHECK_EQUAL(InterestFilter("/a/b/c").doesMatch("/a/b"), false);
+
+  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b>").doesMatch("/a/b"), true);
+  BOOST_CHECK_EQUAL(InterestFilter("/a/b", "<b>").doesMatch("/a/b"), false);
+
+  BOOST_CHECK_EQUAL(InterestFilter("/a/b", "<b>").doesMatch("/a/b/c/b"), false);
+  BOOST_CHECK_EQUAL(InterestFilter("/a/b", "<>*<b>").doesMatch("/a/b/c/b"), true);
+
+  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b>").doesMatch("/a/b/c/d"), false);
+  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b><>*").doesMatch("/a/b/c/d"), true);
+  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b><>*").doesMatch("/a/b"), true);
+  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b><>+").doesMatch("/a/b"), false);
+  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b><>+").doesMatch("/a/b/c"), true);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestInterestFilter
+
+} // namespace tests
+} // namespace ndn
diff --git a/tests/unit-tests/interest.t.cpp b/tests/unit-tests/interest.t.cpp
index 6b2f2cf..b136f95 100644
--- a/tests/unit-tests/interest.t.cpp
+++ b/tests/unit-tests/interest.t.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -20,11 +20,9 @@
  */
 
 #include "interest.hpp"
-#include "interest-filter.hpp"
 #include "data.hpp"
-#include "security/signature-sha256-with-rsa.hpp"
 #include "security/digest-sha256.hpp"
-#include "encoding/buffer-stream.hpp"
+#include "security/signature-sha256-with-rsa.hpp"
 
 #include "boost-test.hpp"
 #include "identity-management-fixture.hpp"
@@ -32,79 +30,405 @@
 namespace ndn {
 namespace tests {
 
-BOOST_FIXTURE_TEST_SUITE(TestInterest, IdentityManagementFixture)
+BOOST_AUTO_TEST_SUITE(TestInterest)
 
-const uint8_t Interest1[] = {
-  0x05,  0x59, // NDN Interest
-      0x07,  0x14, // Name
-          0x08,  0x5, // NameComponent
-              0x6c,  0x6f,  0x63,  0x61,  0x6c,
-          0x08,  0x3, // NameComponent
-              0x6e,  0x64,  0x6e,
-          0x08,  0x6, // NameComponent
-              0x70,  0x72,  0x65,  0x66,  0x69,  0x78,
-      0x09,  0x37, // Selectors
-          0x0d,  0x1,  0x1,  // MinSuffix
-          0x0e,  0x1,  0x1,  // MaxSuffix
-          0x1c, 0x16, // KeyLocator
-              0x07, 0x14, // Name
-                  0x08, 0x04,
-                      0x74, 0x65, 0x73, 0x74,
+// ---- constructor, encode, decode ----
+
+BOOST_AUTO_TEST_CASE(DefaultConstructor)
+{
+  Interest i;
+  BOOST_CHECK_EQUAL(i.getName(), "/");
+  BOOST_CHECK(i.getSelectors().empty());
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
+  BOOST_CHECK_EQUAL(i.hasLink(), false);
+  BOOST_CHECK(!i.hasSelectedDelegation());
+}
+
+BOOST_AUTO_TEST_CASE(EncodeDecodeBasic)
+{
+  const uint8_t WIRE[] = {
+    0x05, 0x1c, // Interest
+          0x07, 0x14, // Name
+                0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // NameComponent
+                0x08, 0x03, 0x6e, 0x64, 0x6e, // NameComponent
+                0x08, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, // NameComponent
+          0x0a, 0x04, // Nonce
+                0x01, 0x00, 0x00, 0x00
+  };
+
+  Interest i1("/local/ndn/prefix");
+  i1.setNonce(1);
+  Block wire1 = i1.wireEncode();
+  BOOST_CHECK_EQUAL_COLLECTIONS(wire1.begin(), wire1.end(), WIRE, WIRE + sizeof(WIRE));
+
+  Interest i2(wire1);
+  BOOST_CHECK_EQUAL(i2.getName(), "/local/ndn/prefix");
+  BOOST_CHECK(i2.getSelectors().empty());
+  BOOST_CHECK_EQUAL(i2.getNonce(), 1);
+  BOOST_CHECK_EQUAL(i2.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
+
+  BOOST_CHECK_EQUAL(i1, i2);
+}
+
+BOOST_AUTO_TEST_CASE(EncodeDecodeFull)
+{
+  const uint8_t WIRE[] = {
+    0x05, 0x25, // Interest
+          0x07, 0x14, // Name
+                0x08, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, // NameComponent
+                0x08, 0x03, 0x6e, 0x64, 0x6e, // NameComponent
+                0x08, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, // NameComponent
+          0x09, 0x03, // Selectors
+                0x0d, 0x01, 0x01,  // MinSuffixComponents
+          0x0a, 0x04, // Nonce
+                0x01, 0x00, 0x00, 0x00,
+          0x0c, 0x02, // InterestLifetime
+                0x03, 0xe8
+  };
+  ///\todo #4055 ForwardingHint
+
+  Interest i1;
+  i1.setName("/local/ndn/prefix");
+  i1.setMinSuffixComponents(1);
+  i1.setNonce(1);
+  i1.setInterestLifetime(time::milliseconds(1000));
+  Block wire1 = i1.wireEncode();
+  BOOST_CHECK_EQUAL_COLLECTIONS(wire1.begin(), wire1.end(), WIRE, WIRE + sizeof(WIRE));
+
+  Interest i2(wire1);
+  BOOST_CHECK_EQUAL(i2.getName(), "/local/ndn/prefix");
+  BOOST_CHECK_EQUAL(i2.getMinSuffixComponents(), 1);
+  BOOST_CHECK_EQUAL(i2.getNonce(), 1);
+  BOOST_CHECK_EQUAL(i2.getInterestLifetime(), time::milliseconds(1000));
+
+  BOOST_CHECK_EQUAL(i1, i2);
+}
+
+const uint8_t LINK[] = {
+  0x06, 0xda, // Data
+      0x07, 0x14, // Name
+          0x08, 0x05,
+              0x6c, 0x6f, 0x63, 0x61, 0x6c,
+          0x08, 0x03,
+              0x6e, 0x64, 0x6e,
+          0x08, 0x06,
+              0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
+      0x14, 0x07, // MetaInfo
+          0x18, 0x01, // ContentType
+              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,
-                      0x6b, 0x65, 0x79,
-                  0x08, 0x07,
-                      0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
-          0x10,  0x14, // Exclude
-              0x08,  0x4, // NameComponent
-                  0x61,  0x6c,  0x65,  0x78,
-              0x08,  0x4, // NameComponent
-                  0x78,  0x78,  0x78,  0x78,
-              0x13,  0x0, // Any
-              0x08,  0x4, // NameComponent
-                  0x79,  0x79,  0x79,  0x79,
-          0x11,  0x1, // ChildSelector
-              0x1,
-      0x0a,  0x4, // Nonce
-          0x1, 0x0, 0x0, 0x00,
-      0x0c,       // InterestLifetime
-          0x2,  0x3,  0xe8
+                      0x6e, 0x64, 0x6e,
+       0x16, 0x1b, // SignatureInfo
+           0x1b, 0x01, // SignatureType
+               0x01,
+       0x1c, 0x16, // KeyLocator
+           0x07, 0x14, // Name
+               0x08, 0x04,
+                   0x74, 0x65, 0x73, 0x74,
+               0x08, 0x03,
+                   0x6b, 0x65, 0x79,
+               0x08, 0x07,
+                   0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
+       0x17, 0x80, // SignatureValue
+           0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
+           0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
+           0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
+           0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
+           0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
+           0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
+           0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
+           0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
+           0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
+           0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
 };
 
-const uint8_t Interest2[] = {
-  0x05,  0x59, // NDN Interest
-      0x07,  0x14, // Name
-          0x08,  0x5, // NameComponent
-              0x6c,  0x6f,  0x63,  0x61,  0x6c,
-          0x08,  0x3, // NameComponent
-              0x6e,  0x64,  0x6e,
-          0x08,  0x6, // NameComponent
-              0x70,  0x72,  0x65,  0x66,  0x69,  0x78,
-      0x09,  0x37, // Selectors
-          0x0d,  0x1,  0x1,  // MinSuffix
-          0x0e,  0x1,  0x1,  // MaxSuffix
-          0x1c, 0x16, // KeyLocator
-              0x07, 0x14, // Name
-                  0x08, 0x04,
-                      0x74, 0x65, 0x73, 0x74,
-                  0x08, 0x03,
-                      0x6b, 0x65, 0x79,
-                  0x08, 0x07,
-                      0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
-          0x10,  0x14, // Exclude
-              0x08,  0x4, // NameComponent
-                  0x61,  0x6c,  0x65,  0x78,
-              0x08,  0x4, // NameComponent
-                  0x78,  0x78,  0x78,  0x78,
-              0x13,  0x0, // Any
-              0x08,  0x4, // NameComponent
-                  0x79,  0x79,  0x79,  0x79,
-          0x11,  0x1, // ChildSelector
-              0x1,
-      0x0a,  0x4, // Nonce
-          0x2, 0x0, 0x0, 0x00,
-      0x0c,       // InterestLifetime
-          0x2,  0x3,  0xe8
-};
+BOOST_AUTO_TEST_CASE(WireDecodeReset) // checks wireDecode resets all fields
+{
+  Interest i1;
+  i1.setName("/test");
+  i1.setMinSuffixComponents(100);
+  i1.setNonce(10);
+  i1.setInterestLifetime(time::seconds(10));
+  i1.setLink(Block(LINK, sizeof(LINK)));
+  i1.setSelectedDelegation(0);
+
+  Interest i2(i1.wireEncode());
+  BOOST_CHECK_EQUAL(i2.getName().toUri(), "/test");
+  BOOST_CHECK_EQUAL(i2.getInterestLifetime(), time::seconds(10));
+  BOOST_CHECK_EQUAL(i2.getMinSuffixComponents(), 100);
+  BOOST_CHECK_EQUAL(i2.getNonce(), 10);
+  BOOST_CHECK_EQUAL(i2.hasLink(), true);
+  BOOST_CHECK_EQUAL(i2.hasSelectedDelegation(), true);
+
+  i2.wireDecode(Interest().wireEncode());
+  BOOST_CHECK_EQUAL(i2.getName().toUri(), "/");
+  BOOST_CHECK_EQUAL(i2.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
+  BOOST_CHECK_EQUAL(i2.getMinSuffixComponents(), -1);
+  BOOST_WARN_NE(i2.getNonce(), 10);
+  BOOST_CHECK_EQUAL(i2.hasLink(), false);
+  BOOST_CHECK_EQUAL(i2.hasSelectedDelegation(), false);
+}
+
+// ---- matching ----
+
+BOOST_AUTO_TEST_CASE(MatchesData)
+{
+  Interest interest;
+  interest.setName("ndn:/A")
+          .setMinSuffixComponents(2)
+          .setMaxSuffixComponents(2)
+          .setPublisherPublicKeyLocator(KeyLocator("ndn:/B"))
+          .setExclude(Exclude().excludeAfter(name::Component("J")));
+
+  Data data("ndn:/A/D");
+  SignatureSha256WithRsa signature(KeyLocator("ndn:/B"));
+  data.setSignature(signature);
+  data.wireEncode();
+  BOOST_CHECK_EQUAL(interest.matchesData(data), true);
+
+  Data data1 = data;
+  data1.setName("ndn:/A"); // violates MinSuffixComponents
+  data1.wireEncode();
+  BOOST_CHECK_EQUAL(interest.matchesData(data1), false);
+
+  Interest interest1 = interest;
+  interest1.setMinSuffixComponents(1);
+  BOOST_CHECK_EQUAL(interest1.matchesData(data1), true);
+
+  Data data2 = data;
+  data2.setName("ndn:/A/E/F"); // violates MaxSuffixComponents
+  data2.wireEncode();
+  BOOST_CHECK_EQUAL(interest.matchesData(data2), false);
+
+  Interest interest2 = interest;
+  interest2.setMaxSuffixComponents(3);
+  BOOST_CHECK_EQUAL(interest2.matchesData(data2), true);
+
+  Data data3 = data;
+  SignatureSha256WithRsa signature3(KeyLocator("ndn:/G")); // violates PublisherPublicKeyLocator
+  data3.setSignature(signature3);
+  data3.wireEncode();
+  BOOST_CHECK_EQUAL(interest.matchesData(data3), false);
+
+  Interest interest3 = interest;
+  interest3.setPublisherPublicKeyLocator(KeyLocator("ndn:/G"));
+  BOOST_CHECK_EQUAL(interest3.matchesData(data3), true);
+
+  Data data4 = data;
+  DigestSha256 signature4; // violates PublisherPublicKeyLocator
+  data4.setSignature(signature4);
+  data4.wireEncode();
+  BOOST_CHECK_EQUAL(interest.matchesData(data4), false);
+
+  Interest interest4 = interest;
+  interest4.setPublisherPublicKeyLocator(KeyLocator());
+  BOOST_CHECK_EQUAL(interest4.matchesData(data4), true);
+
+  Data data5 = data;
+  data5.setName("ndn:/A/J"); // violates Exclude
+  data5.wireEncode();
+  BOOST_CHECK_EQUAL(interest.matchesData(data5), false);
+
+  Interest interest5 = interest;
+  interest5.setExclude(Exclude().excludeAfter(name::Component("K")));
+  BOOST_CHECK_EQUAL(interest5.matchesData(data5), true);
+
+  Data data6 = data;
+  data6.setName("ndn:/H/I"); // violates Name
+  data6.wireEncode();
+  BOOST_CHECK_EQUAL(interest.matchesData(data6), false);
+
+  Data data7 = data;
+  data7.setName("ndn:/A/B");
+  data7.wireEncode();
+
+  Interest interest7("/A/B/sha256digest=D548DECEFC4B880720DC9257A8D815E9DF4465E63742EE55C29133055DAA67C2");
+  BOOST_CHECK_EQUAL(interest7.matchesData(data7), true);
+
+  Interest interest7b("/A/B/sha256digest=0000000000000000000000000000000000000000000000000000000000000000");
+  BOOST_CHECK_EQUAL(interest7b.matchesData(data7), false); // violates implicit digest
+}
+
+BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(MatchesInterest, 1)
+BOOST_AUTO_TEST_CASE(MatchesInterest)
+{
+  Interest interest;
+  interest
+    .setName("/A")
+    .setMinSuffixComponents(2)
+    .setMaxSuffixComponents(2)
+    .setPublisherPublicKeyLocator(KeyLocator("/B"))
+    .setExclude(Exclude().excludeAfter(name::Component("J")))
+    .setNonce(10)
+    .setInterestLifetime(time::seconds(5))
+    .setLink(Block(LINK, sizeof(LINK)));
+
+  Interest other;
+  BOOST_CHECK_EQUAL(interest.matchesInterest(other), false);
+
+  other.setName(interest.getName());
+  BOOST_CHECK_EQUAL(interest.matchesInterest(other), false);
+
+  other.setSelectors(interest.getSelectors());
+  BOOST_CHECK_EQUAL(interest.matchesInterest(other), false); // will match until #3162 implemented
+
+  other.setLink(interest.getLink().wireEncode());
+  BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
+
+  other.setNonce(200);
+  BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
+
+  other.setInterestLifetime(time::hours(5));
+  BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
+
+  other.setSelectedDelegation(0);
+  BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
+}
+
+// ---- field accessors ----
+
+BOOST_AUTO_TEST_CASE(GetNonce)
+{
+  unique_ptr<Interest> i;
+
+  // getNonce automatically assigns a random Nonce, which could be zero.
+  // But it's unlikely to get 100 zeros in a row.
+  uint32_t nonce = 0;
+  int nIterations = 0;
+  do {
+    i = make_unique<Interest>();
+    nonce = i->getNonce();
+  }
+  while (nonce == 0 && ++nIterations < 100);
+  BOOST_CHECK_NE(nonce, 0);
+  BOOST_CHECK(i->hasNonce());
+
+  // Once a Nonce is assigned, it should not change.
+  BOOST_CHECK_EQUAL(i->getNonce(), nonce);
+}
+
+BOOST_AUTO_TEST_CASE(RefreshNonce)
+{
+  Interest i;
+  BOOST_CHECK(!i.hasNonce());
+  i.refreshNonce();
+  BOOST_CHECK(!i.hasNonce());
+
+  i.setNonce(1);
+  BOOST_CHECK(i.hasNonce());
+  i.refreshNonce();
+  BOOST_CHECK(i.hasNonce());
+  BOOST_CHECK_NE(i.getNonce(), 1);
+}
+
+BOOST_AUTO_TEST_CASE(SetInterestLifetime)
+{
+  BOOST_CHECK_THROW(Interest("/A", time::milliseconds(-1)), std::invalid_argument);
+  BOOST_CHECK_NO_THROW(Interest("/A", time::milliseconds(0)));
+
+  Interest i("/local/ndn/prefix");
+  i.setNonce(1);
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
+  BOOST_CHECK_THROW(i.setInterestLifetime(time::milliseconds(-1)), std::invalid_argument);
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
+  i.setInterestLifetime(time::milliseconds(0));
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), time::milliseconds(0));
+  i.setInterestLifetime(time::milliseconds(1));
+  BOOST_CHECK_EQUAL(i.getInterestLifetime(), time::milliseconds(1));
+}
+
+// ---- operators ----
+
+BOOST_AUTO_TEST_CASE(Equality)
+{
+  Interest a;
+  Interest b;
+
+  // if nonce is not set, it would be set to a random value
+  a.setNonce(1);
+  b.setNonce(1);
+
+  BOOST_CHECK_EQUAL(a == b, true);
+  BOOST_CHECK_EQUAL(a != b, false);
+
+  // compare Name
+  a.setName("/A");
+  BOOST_CHECK_EQUAL(a == b, false);
+  BOOST_CHECK_EQUAL(a != b, true);
+
+  b.setName("/B");
+  BOOST_CHECK_EQUAL(a == b, false);
+  BOOST_CHECK_EQUAL(a != b, true);
+
+  b.setName("/A");
+  BOOST_CHECK_EQUAL(a == b, true);
+  BOOST_CHECK_EQUAL(a != b, false);
+
+  // compare Selectors
+  a.setChildSelector(1);
+  BOOST_CHECK_EQUAL(a == b, false);
+  BOOST_CHECK_EQUAL(a != b, true);
+
+  b.setChildSelector(1);
+  BOOST_CHECK_EQUAL(a == b, true);
+  BOOST_CHECK_EQUAL(a != b, false);
+
+  // compare Nonce
+  a.setNonce(100);
+  BOOST_CHECK_EQUAL(a == b, false);
+  BOOST_CHECK_EQUAL(a != b, true);
+
+  b.setNonce(100);
+  BOOST_CHECK_EQUAL(a == b, true);
+  BOOST_CHECK_EQUAL(a != b, false);
+
+  // compare InterestLifetime
+  a.setInterestLifetime(time::seconds(10));
+  BOOST_CHECK_EQUAL(a == b, false);
+  BOOST_CHECK_EQUAL(a != b, true);
+
+  b.setInterestLifetime(time::seconds(10));
+  BOOST_CHECK_EQUAL(a == b, true);
+  BOOST_CHECK_EQUAL(a != b, false);
+
+  ///\todo #4055 compare ForwardingHint
+
+  // compare Link
+  a.setLink(Block(LINK, sizeof(LINK)));
+  BOOST_CHECK_EQUAL(a == b, false);
+  BOOST_CHECK_EQUAL(a != b, true);
+
+  b.setLink(Block(LINK, sizeof(LINK)));
+  BOOST_CHECK_EQUAL(a == b, true);
+  BOOST_CHECK_EQUAL(a != b, false);
+
+  // compare SelectedDelegation
+  BOOST_CHECK_EQUAL(a.hasSelectedDelegation(), false);
+  BOOST_CHECK_EQUAL(b.hasSelectedDelegation(), false);
+
+  a.setSelectedDelegation(Name("/local"));
+  BOOST_CHECK_EQUAL(a == b, false);
+  BOOST_CHECK_EQUAL(a != b, true);
+
+  b.setSelectedDelegation(Name("/local"));
+  BOOST_CHECK_EQUAL(a == b, true);
+  BOOST_CHECK_EQUAL(a != b, false);
+}
+
+BOOST_FIXTURE_TEST_SUITE(LinkSelectedDelegation, IdentityManagementFixture)
 
 const uint8_t InterestWithLink[] = {
   0x05,  0xfb, // Interest
@@ -169,233 +493,6 @@
           0x00
 };
 
-const uint8_t LINK[] = {
-  0x06, 0xda, // Data
-      0x07, 0x14, // Name
-          0x08, 0x05,
-              0x6c, 0x6f, 0x63, 0x61, 0x6c,
-          0x08, 0x03,
-              0x6e, 0x64, 0x6e,
-          0x08, 0x06,
-              0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
-      0x14, 0x07, // MetaInfo
-          0x18, 0x01, // ContentType
-              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,
-       0x16, 0x1b, // SignatureInfo
-           0x1b, 0x01, // SignatureType
-               0x01,
-       0x1c, 0x16, // KeyLocator
-           0x07, 0x14, // Name
-               0x08, 0x04,
-                   0x74, 0x65, 0x73, 0x74,
-               0x08, 0x03,
-                   0x6b, 0x65, 0x79,
-               0x08, 0x07,
-                   0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
-       0x17, 0x80, // SignatureValue
-           0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
-           0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
-           0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
-           0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
-           0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
-           0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
-           0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
-           0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
-           0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
-           0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
-};
-
-const uint8_t InterestWithLinkMissingContentType[] = {
-  0x05,  0xf5, // Interest
-      0x07,  0x14, // Name
-          0x08,  0x5, // NameComponent
-              0x6c,  0x6f,  0x63,  0x61,  0x6c,
-          0x08,  0x3, // NameComponent
-              0x6e,  0x64,  0x6e,
-          0x08,  0x6, // NameComponent
-              0x70,  0x72,  0x65,  0x66,  0x69,  0x78,
-      0x0a,  0x4, // Nonce
-          0x1, 0x0, 0x0, 0x00,
-      0x06, 0xd7, // Data
-          0x07, 0x14, // Name
-              0x08, 0x05,
-                  0x6c, 0x6f, 0x63, 0x61, 0x6c,
-              0x08, 0x03,
-                  0x6e, 0x64, 0x6e,
-              0x08, 0x06,
-                  0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
-          0x14, 0x04, // MetaInfo
-              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,
-           0x16, 0x1b, // SignatureInfo
-               0x1b, 0x01, // SignatureType
-                   0x01,
-           0x1c, 0x16, // KeyLocator
-               0x07, 0x14, // Name
-                   0x08, 0x04,
-                       0x74, 0x65, 0x73, 0x74,
-                   0x08, 0x03,
-                       0x6b, 0x65, 0x79,
-                   0x08, 0x07,
-                       0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
-           0x17, 0x80, // SignatureValue
-               0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
-               0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
-               0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
-               0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
-               0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
-               0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
-               0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
-               0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
-               0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
-               0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
-};
-
-const uint8_t InterestWithLinkNoMetaInfo[] = {
-  0x05,  0xef, // Interest
-      0x07,  0x14, // Name
-          0x08,  0x5, // NameComponent
-              0x6c,  0x6f,  0x63,  0x61,  0x6c,
-          0x08,  0x3, // NameComponent
-              0x6e,  0x64,  0x6e,
-          0x08,  0x6, // NameComponent
-              0x70,  0x72,  0x65,  0x66,  0x69,  0x78,
-      0x0a,  0x4, // Nonce
-          0x1, 0x0, 0x0, 0x00,
-      0x06, 0xd1, // Data
-          0x07, 0x14, // Name
-              0x08, 0x05,
-                  0x6c, 0x6f, 0x63, 0x61, 0x6c,
-              0x08, 0x03,
-                  0x6e, 0x64, 0x6e,
-              0x08, 0x06,
-                  0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
-          0x15, 0x1a, // Content
-              0x1f, 0x0c, // LinkDelegation
-                  0x1e, 0x01, // LinkPreference
-                      0x0a,
-                  0x07, 0x07, // Name
-                      0x08, 0x05,
-                          0x6c, 0x6f, 0x63, 0x61, 0x6c,
-              0x1f, 0x0a, // LinkPreference
-                  0x1e, 0x01, // LinkPreference
-                      0x14,
-                  0x07, 0x05, // Name
-                      0x08, 0x03,
-                          0x6e, 0x64, 0x6e,
-           0x16, 0x1b, // SignatureInfo
-               0x1b, 0x01, // SignatureType
-                   0x01,
-           0x1c, 0x16, // KeyLocator
-               0x07, 0x14, // Name
-                   0x08, 0x04,
-                       0x74, 0x65, 0x73, 0x74,
-                   0x08, 0x03,
-                       0x6b, 0x65, 0x79,
-                   0x08, 0x07,
-                       0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
-           0x17, 0x80, // SignatureValue
-               0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
-               0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
-               0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
-               0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
-               0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
-               0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
-               0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
-               0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
-               0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
-               0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
-};
-
-const uint8_t InterestWithLinkWrongContentType[] = {
-  0x05,  0xf8, // Interest
-      0x07,  0x14, // Name
-          0x08,  0x5, // NameComponent
-              0x6c,  0x6f,  0x63,  0x61,  0x6c,
-          0x08,  0x3, // NameComponent
-              0x6e,  0x64,  0x6e,
-          0x08,  0x6, // NameComponent
-              0x70,  0x72,  0x65,  0x66,  0x69,  0x78,
-      0x0a,  0x4, // Nonce
-          0x1, 0x0, 0x0, 0x00,
-      0x06, 0xda, // Data
-          0x07, 0x14, // Name
-              0x08, 0x05,
-                  0x6c, 0x6f, 0x63, 0x61, 0x6c,
-              0x08, 0x03,
-                  0x6e, 0x64, 0x6e,
-              0x08, 0x06,
-                  0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
-          0x14, 0x07, // MetaInfo
-              0x18, 0x01, // ContentType
-                  0x00,
-              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,
-           0x16, 0x1b, // SignatureInfo
-               0x1b, 0x01, // SignatureType
-                   0x01,
-           0x1c, 0x16, // KeyLocator
-               0x07, 0x14, // Name
-                   0x08, 0x04,
-                       0x74, 0x65, 0x73, 0x74,
-                   0x08, 0x03,
-                       0x6b, 0x65, 0x79,
-                   0x08, 0x07,
-                       0x6c, 0x6f, 0x63, 0x61, 0x74, 0x6f, 0x72,
-           0x17, 0x80, // SignatureValue
-               0x2f, 0xd6, 0xf1, 0x6e, 0x80, 0x6f, 0x10, 0xbe, 0xb1, 0x6f, 0x3e, 0x31, 0xec,
-               0xe3, 0xb9, 0xea, 0x83, 0x30, 0x40, 0x03, 0xfc, 0xa0, 0x13, 0xd9, 0xb3, 0xc6,
-               0x25, 0x16, 0x2d, 0xa6, 0x58, 0x41, 0x69, 0x62, 0x56, 0xd8, 0xb3, 0x6a, 0x38,
-               0x76, 0x56, 0xea, 0x61, 0xb2, 0x32, 0x70, 0x1c, 0xb6, 0x4d, 0x10, 0x1d, 0xdc,
-               0x92, 0x8e, 0x52, 0xa5, 0x8a, 0x1d, 0xd9, 0x96, 0x5e, 0xc0, 0x62, 0x0b, 0xcf,
-               0x3a, 0x9d, 0x7f, 0xca, 0xbe, 0xa1, 0x41, 0x71, 0x85, 0x7a, 0x8b, 0x5d, 0xa9,
-               0x64, 0xd6, 0x66, 0xb4, 0xe9, 0x8d, 0x0c, 0x28, 0x43, 0xee, 0xa6, 0x64, 0xe8,
-               0x55, 0xf6, 0x1c, 0x19, 0x0b, 0xef, 0x99, 0x25, 0x1e, 0xdc, 0x78, 0xb3, 0xa7,
-               0xaa, 0x0d, 0x14, 0x58, 0x30, 0xe5, 0x37, 0x6a, 0x6d, 0xdb, 0x56, 0xac, 0xa3,
-               0xfc, 0x90, 0x7a, 0xb8, 0x66, 0x9c, 0x0e, 0xf6, 0xb7, 0x64, 0xd1
-};
-
 const uint8_t InterestWithSelectedDelegationButNoLink[] = {
   0x05,  0x1f, // Interest
       0x07,  0x14, // Name
@@ -537,142 +634,6 @@
           0x01
 };
 
-BOOST_AUTO_TEST_CASE(DefaultValues)
-{
-  Interest i;
-  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
-  BOOST_CHECK(!i.hasSelectedDelegation());
-}
-
-BOOST_AUTO_TEST_CASE(EncodeInterestLifetime)
-{
-  Interest i;
-  i.setName("/local/ndn/prefix");
-  i.setNonce(1);
-  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
-  BOOST_CHECK_THROW(i.setInterestLifetime(time::milliseconds(-1)), std::invalid_argument);
-  BOOST_CHECK_EQUAL(i.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
-  BOOST_CHECK_NO_THROW(i.setInterestLifetime(time::milliseconds(1)));
-  BOOST_CHECK_EQUAL(i.getInterestLifetime(), time::milliseconds(1));
-  BOOST_CHECK_NO_THROW(i.setInterestLifetime(DEFAULT_INTEREST_LIFETIME));
-
-  const uint8_t expectedDefault[] = {
-    0x05, 0x1c, // Interest
-          0x07, 0x14, // Name
-                0x08, 0x5, // NameComponent
-                      0x6c, 0x6f, 0x63, 0x61, 0x6c,
-                0x08, 0x3, // NameComponent
-                      0x6e, 0x64, 0x6e,
-                0x08, 0x6, // NameComponent
-                      0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
-          0x0a, 0x04, // Nonce
-                0x01, 0x00, 0x00, 0x00, // 1
-  };
-
-  BOOST_CHECK_EQUAL_COLLECTIONS(i.wireEncode().begin(), i.wireEncode().end(),
-                                expectedDefault, expectedDefault + sizeof(expectedDefault));
-
-  const uint8_t expected1000ms[] = {
-    0x05, 0x20, // Interest
-          0x07, 0x14, // Name
-                0x08, 0x5, // NameComponent
-                      0x6c, 0x6f, 0x63, 0x61, 0x6c,
-                0x08, 0x3, // NameComponent
-                      0x6e, 0x64, 0x6e,
-                0x08, 0x6, // NameComponent
-                      0x70, 0x72, 0x65, 0x66, 0x69, 0x78,
-          0x0a, 0x04, // Nonce
-                0x01, 0x00, 0x00, 0x00, // 1
-          0x0c, 0x02, // InterestLifetime
-                0x03, 0xe8
-  };
-
-  BOOST_CHECK_NO_THROW(i.setInterestLifetime(time::milliseconds(1000)));
-  BOOST_CHECK_EQUAL_COLLECTIONS(i.wireEncode().begin(), i.wireEncode().end(),
-                                expected1000ms, expected1000ms + sizeof(expected1000ms));
-}
-
-BOOST_AUTO_TEST_CASE(InterestEqualityChecks)
-{
-  // Interest ::= INTEREST-TYPE TLV-LENGTH
-  //                Name
-  //                Selectors?
-  //                Nonce
-  //                InterestLifetime?
-  //                Link?
-  //                SelectedDelegation?
-
-  Interest a;
-  Interest b;
-
-  // if nonce is not set, it will be set to a random value
-  a.setNonce(1);
-  b.setNonce(1);
-
-  BOOST_CHECK_EQUAL(a == b, true);
-  BOOST_CHECK_EQUAL(a != b, false);
-
-  // check comparison on Name
-  a.setName("ndn:/A");
-  BOOST_CHECK_EQUAL(a == b, false);
-  BOOST_CHECK_EQUAL(a != b, true);
-
-  b.setName("ndn:/B");
-  BOOST_CHECK_EQUAL(a == b, false);
-  BOOST_CHECK_EQUAL(a != b, true);
-
-  b.setName("ndn:/A");
-  BOOST_CHECK_EQUAL(a == b, true);
-  BOOST_CHECK_EQUAL(a != b, false);
-
-  // check comparison on Selectors
-  a.setChildSelector(1);
-  BOOST_CHECK_EQUAL(a == b, false);
-  BOOST_CHECK_EQUAL(a != b, true);
-
-  b.setChildSelector(1);
-  BOOST_CHECK_EQUAL(a == b, true);
-  BOOST_CHECK_EQUAL(a != b, false);
-
-  // check comparison on Nonce
-  a.setNonce(100);
-  BOOST_CHECK_EQUAL(a == b, false);
-  BOOST_CHECK_EQUAL(a != b, true);
-
-  b.setNonce(100);
-  BOOST_CHECK_EQUAL(a == b, true);
-  BOOST_CHECK_EQUAL(a != b, false);
-
-  // check comparison on InterestLifetime
-  a.setInterestLifetime(time::seconds(10));
-  BOOST_CHECK_EQUAL(a == b, false);
-  BOOST_CHECK_EQUAL(a != b, true);
-
-  b.setInterestLifetime(time::seconds(10));
-  BOOST_CHECK_EQUAL(a == b, true);
-  BOOST_CHECK_EQUAL(a != b, false);
-
-  a.setLink(Block(LINK, sizeof(LINK)));
-  BOOST_CHECK_EQUAL(a == b, false);
-  BOOST_CHECK_EQUAL(a != b, true);
-
-  b.setLink(Block(LINK, sizeof(LINK)));
-  BOOST_CHECK_EQUAL(a == b, true);
-  BOOST_CHECK_EQUAL(a != b, false);
-
-  // Selected Delegation
-  BOOST_CHECK_EQUAL(a.hasSelectedDelegation(), false);
-  BOOST_CHECK_EQUAL(b.hasSelectedDelegation(), false);
-
-  a.setSelectedDelegation(Name("/local"));
-  BOOST_CHECK_EQUAL(a == b, false);
-  BOOST_CHECK_EQUAL(a != b, true);
-
-  b.setSelectedDelegation(Name("/local"));
-  BOOST_CHECK_EQUAL(a == b, true);
-  BOOST_CHECK_EQUAL(a != b, false);
-}
-
 BOOST_AUTO_TEST_CASE(LinkObject)
 {
   Link link1("test", {{100, "/test3"}, {20, "/test2"}, {10, "/test1"}});
@@ -794,30 +755,6 @@
   BOOST_CHECK_EQUAL(i.getSelectedDelegation(), Name("ndn"));
 }
 
-BOOST_AUTO_TEST_CASE(LinkObjectMissingContentType)
-{
-  Block interestBlock(InterestWithLinkMissingContentType,
-                      sizeof(InterestWithLinkMissingContentType));
-
-  BOOST_CHECK_THROW(Interest(interestBlock).getLink(), tlv::Error);
-}
-
-BOOST_AUTO_TEST_CASE(LinkObjectNoMetaInfo)
-{
-  Block interestBlock(InterestWithLinkNoMetaInfo,
-                      sizeof(InterestWithLinkNoMetaInfo));
-
-  BOOST_CHECK_THROW(Interest(interestBlock).getLink(), tlv::Error);
-}
-
-BOOST_AUTO_TEST_CASE(LinkObjectWrongContentType)
-{
-  Block interestBlock(InterestWithLinkWrongContentType,
-                      sizeof(InterestWithLinkWrongContentType));
-
-  BOOST_CHECK_THROW(Interest(interestBlock).getLink(), tlv::Error);
-}
-
 BOOST_AUTO_TEST_CASE(InterestContainingSelectedDelegationButNoLink)
 {
   Block interestBlock(InterestWithSelectedDelegationButNoLink,
@@ -866,263 +803,7 @@
   BOOST_CHECK_THROW(a.setSelectedDelegation(4), Interest::Error);
 }
 
-BOOST_AUTO_TEST_CASE(Decode)
-{
-  Block interestBlock(Interest1, sizeof(Interest1));
-
-  ndn::Interest i;
-  BOOST_REQUIRE_NO_THROW(i.wireDecode(interestBlock));
-
-  BOOST_CHECK_EQUAL(i.getName().toUri(), "/local/ndn/prefix");
-  BOOST_CHECK_EQUAL(i.getInterestLifetime(), time::milliseconds(1000));
-  BOOST_CHECK_EQUAL(i.getMinSuffixComponents(), 1);
-  BOOST_CHECK_EQUAL(i.getMaxSuffixComponents(), 1);
-  BOOST_CHECK_EQUAL(i.getPublisherPublicKeyLocator().getType(),
-                    static_cast<uint32_t>(KeyLocator::KeyLocator_Name));
-  BOOST_CHECK_EQUAL(i.getPublisherPublicKeyLocator().getName(), "ndn:/test/key/locator");
-  BOOST_CHECK_EQUAL(i.getChildSelector(), 1);
-  BOOST_CHECK_EQUAL(i.getMustBeFresh(), false);
-  BOOST_CHECK_EQUAL(i.getExclude().toUri(), "alex,xxxx,*,yyyy");
-  BOOST_CHECK_EQUAL(i.getNonce(), 1U);
-  BOOST_CHECK_EQUAL(i.hasLink(), false);
-  BOOST_CHECK_EQUAL(i.hasSelectedDelegation(), false);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeFromStream)
-{
-  boost::iostreams::stream<boost::iostreams::array_source> is(
-    reinterpret_cast<const char *>(Interest1), sizeof(Interest1));
-
-  Block interestBlock = Block::fromStream(is);
-
-  ndn::Interest i;
-  BOOST_REQUIRE_NO_THROW(i.wireDecode(interestBlock));
-
-  BOOST_CHECK_EQUAL(i.getName().toUri(), "/local/ndn/prefix");
-  BOOST_CHECK_EQUAL(i.getInterestLifetime(), time::milliseconds(1000));
-  BOOST_CHECK_EQUAL(i.getMinSuffixComponents(), 1);
-  BOOST_CHECK_EQUAL(i.getMaxSuffixComponents(), 1);
-  BOOST_CHECK_EQUAL(i.getChildSelector(), 1);
-  BOOST_CHECK_EQUAL(i.getMustBeFresh(), false);
-  BOOST_CHECK_EQUAL(i.getExclude().toUri(), "alex,xxxx,*,yyyy");
-  BOOST_CHECK_EQUAL(i.getNonce(), 1U);
-  BOOST_CHECK_EQUAL(i.hasLink(), false);
-  BOOST_CHECK_EQUAL(i.hasSelectedDelegation(), false);
-}
-
-BOOST_AUTO_TEST_CASE(Encode)
-{
-  ndn::Interest i(ndn::Name("/local/ndn/prefix"));
-  i.setInterestLifetime(time::milliseconds(1000));
-  i.setMinSuffixComponents(1);
-  i.setMaxSuffixComponents(1);
-  i.setPublisherPublicKeyLocator(KeyLocator("ndn:/test/key/locator"));
-  i.setChildSelector(1);
-  i.setMustBeFresh(false);
-  Exclude exclude;
-  exclude
-    .excludeOne(name::Component("alex"))
-    .excludeRange(name::Component("xxxx"), name::Component("yyyy"));
-  i.setExclude(exclude);
-  i.setNonce(1);
-
-  BOOST_CHECK_EQUAL(i.hasWire(), false);
-  const Block& wire = i.wireEncode();
-  BOOST_CHECK_EQUAL(i.hasWire(), true);
-
-  BOOST_CHECK_EQUAL_COLLECTIONS(Interest1, Interest1 + sizeof(Interest1),
-                                wire.begin(), wire.end());
-
-  const uint8_t* originalWire = wire.wire();
-  i.setNonce(2);
-  BOOST_CHECK_EQUAL(i.hasWire(), true);
-  BOOST_CHECK_EQUAL(originalWire, i.wireEncode().wire());
-  BOOST_CHECK_EQUAL(i.hasWire(), true);
-
-  BOOST_CHECK_EQUAL_COLLECTIONS(Interest2, Interest2 + sizeof(Interest2),
-                                wire.begin(), wire.end());
-
-  std::ostringstream strStream;
-  BOOST_CHECK_NO_THROW(strStream << i);
-
-  BOOST_CHECK_EQUAL(strStream.str(),
-                    "/local/ndn/prefix?"
-                    "ndn.MinSuffixComponents=1&ndn.MaxSuffixComponents=1&"
-                    "ndn.ChildSelector=1&"
-                    "ndn.InterestLifetime=1000&"
-                    "ndn.Nonce=2&ndn.Exclude=alex,xxxx,*,yyyy");
-
-  i.refreshNonce();
-  BOOST_CHECK_EQUAL(i.hasWire(), true);
-  BOOST_CHECK_EQUAL(originalWire, i.wireEncode().wire());
-  BOOST_CHECK_NE(i.getNonce(), 2);
-}
-
-BOOST_AUTO_TEST_CASE(DecodeEncode) // this test case to ensure that wireDecode resets all the fields
-{
-  Interest i1;
-  i1.setName("/test");
-  i1.setMinSuffixComponents(100);
-  i1.setNonce(10);
-  i1.setInterestLifetime(time::seconds(10));
-  i1.setLink(Block(LINK, sizeof(LINK)));
-  i1.setSelectedDelegation(0);
-
-  Interest i2(i1.wireEncode());
-
-  BOOST_CHECK_EQUAL(i2.getName().toUri(), "/test");
-  BOOST_CHECK_EQUAL(i2.getInterestLifetime(), time::seconds(10));
-  BOOST_CHECK_EQUAL(i2.getMinSuffixComponents(), 100);
-  BOOST_CHECK_EQUAL(i2.getNonce(), 10);
-  BOOST_CHECK_EQUAL(i2.hasLink(), true);
-  BOOST_CHECK_EQUAL(i2.hasSelectedDelegation(), true);
-
-  i2.wireDecode(Interest().wireEncode());
-
-  BOOST_CHECK_EQUAL(i2.getName().toUri(), "/");
-  BOOST_CHECK_EQUAL(i2.getInterestLifetime(), DEFAULT_INTEREST_LIFETIME);
-  BOOST_CHECK_EQUAL(i2.getMinSuffixComponents(), -1);
-  BOOST_WARN_NE(i2.getNonce(), 10);
-  BOOST_CHECK_EQUAL(i2.hasLink(), false);
-  BOOST_CHECK_EQUAL(i2.hasSelectedDelegation(), false);
-}
-
-BOOST_AUTO_TEST_CASE(MatchesData)
-{
-  Interest interest;
-  interest.setName("ndn:/A")
-          .setMinSuffixComponents(2)
-          .setMaxSuffixComponents(2)
-          .setPublisherPublicKeyLocator(KeyLocator("ndn:/B"))
-          .setExclude(Exclude().excludeAfter(name::Component("J")));
-
-  Data data("ndn:/A/D");
-  SignatureSha256WithRsa signature(KeyLocator("ndn:/B"));
-  data.setSignature(signature);
-  data.wireEncode();
-  BOOST_CHECK_EQUAL(interest.matchesData(data), true);
-
-  Data data1 = data;
-  data1.setName("ndn:/A"); // violates MinSuffixComponents
-  data1.wireEncode();
-  BOOST_CHECK_EQUAL(interest.matchesData(data1), false);
-
-  Interest interest1 = interest;
-  interest1.setMinSuffixComponents(1);
-  BOOST_CHECK_EQUAL(interest1.matchesData(data1), true);
-
-  Data data2 = data;
-  data2.setName("ndn:/A/E/F"); // violates MaxSuffixComponents
-  data2.wireEncode();
-  BOOST_CHECK_EQUAL(interest.matchesData(data2), false);
-
-  Interest interest2 = interest;
-  interest2.setMaxSuffixComponents(3);
-  BOOST_CHECK_EQUAL(interest2.matchesData(data2), true);
-
-  Data data3 = data;
-  SignatureSha256WithRsa signature3(KeyLocator("ndn:/G")); // violates PublisherPublicKeyLocator
-  data3.setSignature(signature3);
-  data3.wireEncode();
-  BOOST_CHECK_EQUAL(interest.matchesData(data3), false);
-
-  Interest interest3 = interest;
-  interest3.setPublisherPublicKeyLocator(KeyLocator("ndn:/G"));
-  BOOST_CHECK_EQUAL(interest3.matchesData(data3), true);
-
-  Data data4 = data;
-  DigestSha256 signature4; // violates PublisherPublicKeyLocator
-  data4.setSignature(signature4);
-  data4.wireEncode();
-  BOOST_CHECK_EQUAL(interest.matchesData(data4), false);
-
-  Interest interest4 = interest;
-  interest4.setPublisherPublicKeyLocator(KeyLocator());
-  BOOST_CHECK_EQUAL(interest4.matchesData(data4), true);
-
-  Data data5 = data;
-  data5.setName("ndn:/A/J"); // violates Exclude
-  data5.wireEncode();
-  BOOST_CHECK_EQUAL(interest.matchesData(data5), false);
-
-  Interest interest5 = interest;
-  interest5.setExclude(Exclude().excludeAfter(name::Component("K")));
-  BOOST_CHECK_EQUAL(interest5.matchesData(data5), true);
-
-  Data data6 = data;
-  data6.setName("ndn:/H/I"); // violates Name
-  data6.wireEncode();
-  BOOST_CHECK_EQUAL(interest.matchesData(data6), false);
-
-  Data data7 = data;
-  data7.setName("ndn:/A/B");
-  data7.wireEncode();
-
-  Interest interest7("/A/B/sha256digest=D548DECEFC4B880720DC9257A8D815E9DF4465E63742EE55C29133055DAA67C2");
-  BOOST_CHECK_EQUAL(interest7.matchesData(data7), true);
-
-  Interest interest7b("/A/B/sha256digest=0000000000000000000000000000000000000000000000000000000000000000");
-  BOOST_CHECK_EQUAL(interest7b.matchesData(data7), false); // violates implicit digest
-}
-
-BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(MatchesInterest, 1)
-BOOST_AUTO_TEST_CASE(MatchesInterest)
-{
-  Interest interest;
-  interest
-    .setName("ndn:/A")
-    .setMinSuffixComponents(2)
-    .setMaxSuffixComponents(2)
-    .setPublisherPublicKeyLocator(KeyLocator("ndn:/B"))
-    .setExclude(Exclude().excludeAfter(name::Component("J")))
-    .setNonce(10)
-    .setInterestLifetime(time::seconds(5));
-
-  Link link("/A/LINK", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}});
-  m_keyChain.sign(link);
-  interest.setLink(link.wireEncode());
-
-  Interest other;
-  BOOST_CHECK_EQUAL(interest.matchesInterest(other), false);
-
-  other.setName(interest.getName());
-  BOOST_CHECK_EQUAL(interest.matchesInterest(other), false);
-
-  // TODO: will match until #3162 implemented
-  other.setSelectors(interest.getSelectors());
-  BOOST_CHECK_EQUAL(interest.matchesInterest(other), false);
-
-  other.setLink(interest.getLink().wireEncode());
-  BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
-
-  other.setNonce(200);
-  BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
-
-  other.setInterestLifetime(time::hours(5));
-  BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
-
-  other.setSelectedDelegation(0);
-  BOOST_CHECK_EQUAL(interest.matchesInterest(other), true);
-}
-
-BOOST_AUTO_TEST_CASE(InterestFilterMatching)
-{
-  BOOST_CHECK_EQUAL(InterestFilter("/a").doesMatch("/a/b"), true);
-  BOOST_CHECK_EQUAL(InterestFilter("/a/b").doesMatch("/a/b"), true);
-  BOOST_CHECK_EQUAL(InterestFilter("/a/b/c").doesMatch("/a/b"), false);
-
-  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b>").doesMatch("/a/b"), true);
-  BOOST_CHECK_EQUAL(InterestFilter("/a/b", "<b>").doesMatch("/a/b"), false);
-
-  BOOST_CHECK_EQUAL(InterestFilter("/a/b", "<b>").doesMatch("/a/b/c/b"), false);
-  BOOST_CHECK_EQUAL(InterestFilter("/a/b", "<>*<b>").doesMatch("/a/b/c/b"), true);
-
-  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b>").doesMatch("/a/b/c/d"), false);
-  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b><>*").doesMatch("/a/b/c/d"), true);
-  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b><>*").doesMatch("/a/b"), true);
-  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b><>+").doesMatch("/a/b"), false);
-  BOOST_CHECK_EQUAL(InterestFilter("/a", "<b><>+").doesMatch("/a/b/c"), true);
-}
+BOOST_AUTO_TEST_SUITE_END() // LinkSelectedDelegation
 
 BOOST_AUTO_TEST_SUITE_END() // TestInterest