table: pit::Entry checks Interest matches entry when updating in/out-record

pit::Entry::canMatch is the single place to determine whether an Interest
matches an Interest table entry. This condition is asserted when an in/out-
record is inserted or updated. This prevents a strategy from incorrectly
picking an Interest that is incompatible with the Interest table entry.

refs #1756

Change-Id: Ibf61a0e2e32b7a0e04e581f01ef07b791c6010a2
diff --git a/daemon/table/pit-entry.cpp b/daemon/table/pit-entry.cpp
index 522f4e2..157b9f9 100644
--- a/daemon/table/pit-entry.cpp
+++ b/daemon/table/pit-entry.cpp
@@ -35,6 +35,18 @@
 {
 }
 
+bool
+Entry::canMatch(const Interest& interest, size_t nEqualNameComps) const
+{
+  BOOST_ASSERT(m_interest->getName().compare(0, nEqualNameComps,
+                                             interest.getName(), 0, nEqualNameComps) == 0);
+
+  return m_interest->getName().compare(nEqualNameComps, Name::npos,
+                                       interest.getName(), nEqualNameComps) == 0 &&
+         m_interest->getSelectors() == interest.getSelectors();
+  /// \todo #3162 match Link field
+}
+
 InRecordCollection::iterator
 Entry::getInRecord(const Face& face)
 {
@@ -45,6 +57,8 @@
 InRecordCollection::iterator
 Entry::insertOrUpdateInRecord(Face& face, const Interest& interest)
 {
+  BOOST_ASSERT(this->canMatch(interest));
+
   auto it = std::find_if(m_inRecords.begin(), m_inRecords.end(),
     [&face] (const InRecord& inRecord) { return &inRecord.getFace() == &face; });
   if (it == m_inRecords.end()) {
@@ -82,6 +96,8 @@
 OutRecordCollection::iterator
 Entry::insertOrUpdateOutRecord(Face& face, const Interest& interest)
 {
+  BOOST_ASSERT(this->canMatch(interest));
+
   auto it = std::find_if(m_outRecords.begin(), m_outRecords.end(),
     [&face] (const OutRecord& outRecord) { return &outRecord.getFace() == &face; });
   if (it == m_outRecords.end()) {
diff --git a/daemon/table/pit-entry.hpp b/daemon/table/pit-entry.hpp
index d28cb90..31a2f04 100644
--- a/daemon/table/pit-entry.hpp
+++ b/daemon/table/pit-entry.hpp
@@ -79,6 +79,13 @@
     return m_interest->getName();
   }
 
+  /** \return whether interest matches this entry
+   *  \param interest the Interest
+   *  \param nEqualNameComps number of initial name components guaranteed to be equal
+   */
+  bool
+  canMatch(const Interest& interest, size_t nEqualNameComps = 0) const;
+
 public: // in-record
   /** \return collection of in-records
    */
diff --git a/daemon/table/pit.cpp b/daemon/table/pit.cpp
index 8fc78bf..3256b89 100644
--- a/daemon/table/pit.cpp
+++ b/daemon/table/pit.cpp
@@ -64,14 +64,10 @@
   size_t nteNameLen = nteName.size();
   const std::vector<shared_ptr<Entry>>& pitEntries = nte->getPitEntries();
   auto it = std::find_if(pitEntries.begin(), pitEntries.end(),
-    [&interest, nteNameLen] (const shared_ptr<Entry>& entry) -> bool {
-      // initial part of the name is guaranteed to be the same
-      BOOST_ASSERT(entry->getInterest().getName().compare(0, nteNameLen,
-                   interest.getName(), 0, nteNameLen) == 0);
-      // compare implicit digest (or its absence) only
-      return entry->getInterest().getName().compare(nteNameLen, Name::npos,
-                                                    interest.getName(), nteNameLen) == 0 &&
-             entry->getInterest().getSelectors() == interest.getSelectors();
+    [&interest, nteNameLen] (const shared_ptr<Entry>& entry) {
+      // initial part of name is guaranteed to be equal by NameTree
+      // check implicit digest (or its absence) only
+      return entry->canMatch(interest, nteNameLen);
     });
   if (it != pitEntries.end()) {
     return {*it, false};