fw: introduce afterReceiveData strategy trigger

Change-Id: Ia805f1bd48f481c9b903b6ce5c388dd66fbbb7d1
refs: #4290
diff --git a/tests/daemon/fw/dummy-strategy.cpp b/tests/daemon/fw/dummy-strategy.cpp
index b37171f..1dd79dd 100644
--- a/tests/daemon/fw/dummy-strategy.cpp
+++ b/tests/daemon/fw/dummy-strategy.cpp
@@ -47,6 +47,7 @@
   , afterReceiveInterest_count(0)
   , beforeSatisfyInterest_count(0)
   , afterContentStoreHit_count(0)
+  , afterReceiveData_count(0)
   , afterReceiveNack_count(0)
 {
   this->setInstanceName(name);
@@ -79,7 +80,16 @@
 {
   ++afterContentStoreHit_count;
 
-  this->sendData(pitEntry, data, inFace);
+  Strategy::afterContentStoreHit(pitEntry, inFace, data);
+}
+
+void
+DummyStrategy::afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
+                                const Face& inFace, const Data& data)
+{
+  ++afterReceiveData_count;
+
+  Strategy::afterReceiveData(pitEntry, inFace, data);
 }
 
 void
diff --git a/tests/daemon/fw/dummy-strategy.hpp b/tests/daemon/fw/dummy-strategy.hpp
index 24a432c..697d5ae 100644
--- a/tests/daemon/fw/dummy-strategy.hpp
+++ b/tests/daemon/fw/dummy-strategy.hpp
@@ -73,6 +73,10 @@
                        const Face& inFace, const Data& data) override;
 
   void
+  afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
+                   const Face& inFace, const Data& data) override;
+
+  void
   afterReceiveNack(const Face& inFace, const lp::Nack& nack,
                    const shared_ptr<pit::Entry>& pitEntry) override;
 
@@ -93,6 +97,7 @@
   int afterReceiveInterest_count;
   int beforeSatisfyInterest_count;
   int afterContentStoreHit_count;
+  int afterReceiveData_count;
   int afterReceiveNack_count;
 
   shared_ptr<Face> interestOutFace;
diff --git a/tests/daemon/fw/pit-expiry.t.cpp b/tests/daemon/fw/pit-expiry.t.cpp
index 1977458..07c79c9 100644
--- a/tests/daemon/fw/pit-expiry.t.cpp
+++ b/tests/daemon/fw/pit-expiry.t.cpp
@@ -78,7 +78,7 @@
   {
     DummyStrategy::beforeSatisfyInterest(pitEntry, inFace, data);
 
-    if (beforeSatisfyInterest_count <= 1) {
+    if (beforeSatisfyInterest_count <= 2) {
       setExpiryTimer(pitEntry, 190_ms);
     }
   }
@@ -95,6 +95,19 @@
   }
 
   void
+  afterReceiveData(const shared_ptr<pit::Entry>& pitEntry,
+                   const Face& inFace, const Data& data) override
+  {
+    ++afterReceiveData_count;
+
+    if (afterReceiveData_count <= 2) {
+      setExpiryTimer(pitEntry, 290_ms);
+    }
+
+    this->sendDataToAll(pitEntry, inFace, data);
+  }
+
+  void
   afterReceiveNack(const Face& inFace, const lp::Nack& nack,
                    const shared_ptr<pit::Entry>& pitEntry) override
   {
@@ -259,12 +272,70 @@
 
   auto face1 = make_shared<DummyFace>();
   auto face2 = make_shared<DummyFace>();
+  auto face3 = make_shared<DummyFace>();
+  forwarder.addFace(face1);
+  forwarder.addFace(face2);
+  forwarder.addFace(face3);
+
+  Name strategyA("/strategyA/%FD%01");
+  Name strategyB("/strategyB/%FD%01");
+  PitExpiryTestStrategy::registerAs(strategyA);
+  PitExpiryTestStrategy::registerAs(strategyB);
+  auto& sA = choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
+  auto& sB = choose<PitExpiryTestStrategy>(forwarder, "/A/0", strategyB);
+  Pit& pit = forwarder.getPit();
+
+  shared_ptr<Interest> interest1 = makeInterest("/A");
+  shared_ptr<Interest> interest2 = makeInterest("/A/0");
+  interest1->setInterestLifetime(90_ms);
+  interest2->setInterestLifetime(90_ms);
+  shared_ptr<Data> data = makeData("/A/0");
+
+  face1->receiveInterest(*interest1);
+  face2->receiveInterest(*interest2);
+  BOOST_CHECK_EQUAL(pit.size(), 2);
+
+  // beforeSatisfyInterest: the first Data prolongs PIT expiry timer by 190 ms
+  this->advanceClocks(30_ms);
+  face3->receiveData(*data);
+  this->advanceClocks(189_ms);
+  BOOST_CHECK_EQUAL(pit.size(), 2);
+  this->advanceClocks(2_ms);
+  BOOST_CHECK_EQUAL(pit.size(), 0);
+
+  face1->receiveInterest(*interest1);
+  face2->receiveInterest(*interest2);
+
+  // beforeSatisfyInterest: the second Data prolongs PIT expiry timer
+  // and the third one sets the timer to now
+  this->advanceClocks(30_ms);
+  face3->receiveData(*data);
+  this->advanceClocks(1_ms);
+  BOOST_CHECK_EQUAL(pit.size(), 2);
+
+  this->advanceClocks(30_ms);
+  face3->receiveData(*data);
+  this->advanceClocks(1_ms);
+  BOOST_CHECK_EQUAL(pit.size(), 0);
+
+  BOOST_CHECK_EQUAL(sA.beforeSatisfyInterest_count, 3);
+  BOOST_CHECK_EQUAL(sB.beforeSatisfyInterest_count, 3);
+  BOOST_CHECK_EQUAL(sA.afterReceiveData_count, 0);
+  BOOST_CHECK_EQUAL(sB.afterReceiveData_count, 0);
+}
+
+BOOST_AUTO_TEST_CASE(ResetTimerAfterReceiveData)
+{
+  Forwarder forwarder;
+
+  auto face1 = make_shared<DummyFace>();
+  auto face2 = make_shared<DummyFace>();
   forwarder.addFace(face1);
   forwarder.addFace(face2);
 
   Name strategyA("/strategyA/%FD%01");
   PitExpiryTestStrategy::registerAs(strategyA);
-  choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
+  auto& sA = choose<PitExpiryTestStrategy>(forwarder, "/A", strategyA);
 
   Pit& pit = forwarder.getPit();
 
@@ -274,17 +345,30 @@
 
   face1->receiveInterest(*interest);
 
+  // afterReceiveData: the first Data prolongs PIT expiry timer by 290 ms
   this->advanceClocks(30_ms);
   face2->receiveData(*data);
+  this->advanceClocks(289_ms);
+  BOOST_CHECK_EQUAL(pit.size(), 1);
+  this->advanceClocks(2_ms);
+  BOOST_CHECK_EQUAL(pit.size(), 0);
 
+  face1->receiveInterest(*interest);
+
+  // afterReceiveData: the second Data prolongs PIT expiry timer
+  // and the third one sets the timer to now
+  this->advanceClocks(30_ms);
+  face2->receiveData(*data);
   this->advanceClocks(1_ms);
   BOOST_CHECK_EQUAL(pit.size(), 1);
 
   this->advanceClocks(30_ms);
   face2->receiveData(*data);
-
   this->advanceClocks(1_ms);
   BOOST_CHECK_EQUAL(pit.size(), 0);
+
+  BOOST_CHECK_EQUAL(sA.beforeSatisfyInterest_count, 0);
+  BOOST_CHECK_EQUAL(sA.afterReceiveData_count, 3);
 }
 
 BOOST_AUTO_TEST_CASE(ReceiveNackAfterResetTimer)