fw: hasPendingOutRecords considers Nack

refs #3545

Change-Id: I986187f58e60090518df2a55a8bd9c1f05771b03
diff --git a/daemon/fw/pit-algorithm.cpp b/daemon/fw/pit-algorithm.cpp
index ecc8acd..a9ef7ea 100644
--- a/daemon/fw/pit-algorithm.cpp
+++ b/daemon/fw/pit-algorithm.cpp
@@ -115,7 +115,10 @@
 {
   time::steady_clock::TimePoint now = time::steady_clock::now();
   return std::any_of(pitEntry.out_begin(), pitEntry.out_end(),
-    [&now] (const pit::OutRecord& outRecord) { return outRecord.getExpiry() >= now; });
+                      [&now] (const pit::OutRecord& outRecord) {
+                        return outRecord.getExpiry() >= now &&
+                               outRecord.getIncomingNack() == nullptr;
+                      });
 }
 
 } // namespace fw
diff --git a/daemon/fw/pit-algorithm.hpp b/daemon/fw/pit-algorithm.hpp
index f901316..ed47725 100644
--- a/daemon/fw/pit-algorithm.hpp
+++ b/daemon/fw/pit-algorithm.hpp
@@ -106,8 +106,7 @@
 findDuplicateNonce(const pit::Entry& pitEntry, uint32_t nonce, const Face& face);
 
 /** \brief determine whether \p pitEntry has any pending out-records
- *  \return true if there is one or more unexpired OutRecords
- *  \todo #3545 take Nack into consideration
+ *  \return true if there is at least one out-record waiting for Data
  */
 bool
 hasPendingOutRecords(const pit::Entry& pitEntry);
diff --git a/tests/daemon/fw/pit-algorithm.t.cpp b/tests/daemon/fw/pit-algorithm.t.cpp
index 239823c..cf3eea0 100644
--- a/tests/daemon/fw/pit-algorithm.t.cpp
+++ b/tests/daemon/fw/pit-algorithm.t.cpp
@@ -190,9 +190,39 @@
   BOOST_CHECK_EQUAL(findDuplicateNonce(entry5, 19004, *face2), DUPLICATE_NONCE_NONE);
 }
 
-BOOST_AUTO_TEST_CASE(HasPendingOutRecords)
+BOOST_FIXTURE_TEST_CASE(HasPendingOutRecords, UnitTestTimeFixture)
 {
-  /// \todo #3545
+  auto face1 = make_shared<DummyFace>();
+  auto face2 = make_shared<DummyFace>();
+  auto face3 = make_shared<DummyFace>();
+
+  shared_ptr<Interest> interest = makeInterest("ndn:/totzXG0d");
+  interest->setNonce(29321);
+
+  pit::Entry entry(*interest);
+  BOOST_CHECK_EQUAL(hasPendingOutRecords(entry), false);
+
+  // Interest-Data
+  entry.insertOrUpdateOutRecord(face1, *interest);
+  BOOST_CHECK_EQUAL(hasPendingOutRecords(entry), true);
+  entry.deleteOutRecord(*face1);
+  BOOST_CHECK_EQUAL(hasPendingOutRecords(entry), false);
+
+  // Interest-Nack
+  entry.insertOrUpdateOutRecord(face2, *interest);
+  BOOST_CHECK_EQUAL(hasPendingOutRecords(entry), true);
+  pit::OutRecordCollection::iterator outR = entry.getOutRecord(*face2);
+  BOOST_REQUIRE(outR != entry.out_end());
+  lp::Nack nack = makeNack("ndn:/totzXG0d", 29321, lp::NackReason::DUPLICATE);
+  bool isNackAccepted = outR->setIncomingNack(nack); // Nack arrival
+  BOOST_REQUIRE(isNackAccepted);
+  BOOST_CHECK_EQUAL(hasPendingOutRecords(entry), false);
+
+  // Interest-timeout
+  entry.insertOrUpdateOutRecord(face3, *interest);
+  BOOST_CHECK_EQUAL(hasPendingOutRecords(entry), true);
+  this->advanceClocks(ndn::DEFAULT_INTEREST_LIFETIME, 2);
+  BOOST_CHECK_EQUAL(hasPendingOutRecords(entry), false);
 }
 
 BOOST_AUTO_TEST_SUITE_END() // TestPitAlgorithm