fw: abstract Nack processing out of BestRouteStrategy2

refs #3176

Change-Id: Ib220269ff52acc47c65f854a610941afd862ad41
diff --git a/tests/daemon/fw/best-route-strategy2.t.cpp b/tests/daemon/fw/best-route-strategy2.t.cpp
index fcd7b9f..69328ff 100644
--- a/tests/daemon/fw/best-route-strategy2.t.cpp
+++ b/tests/daemon/fw/best-route-strategy2.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -220,242 +220,6 @@
 
 BOOST_AUTO_TEST_SUITE_END() // NoRouteNack
 
-BOOST_AUTO_TEST_SUITE(IncomingNack)
-
-BOOST_AUTO_TEST_CASE(OneUpstream) // one upstream, send Nack when Nack arrives
-{
-  fib::Entry& fibEntry = *fib.insert(Name()).first;
-  fibEntry.addNextHop(*face3, 10);
-  fibEntry.addNextHop(*face4, 20);
-  fibEntry.addNextHop(*face5, 30);
-
-  shared_ptr<Interest> interest1 = makeInterest("/McQYjMbm", 992);
-  shared_ptr<Interest> interest2 = makeInterest("/McQYjMbm", 114);
-  shared_ptr<pit::Entry> pitEntry = pit.insert(*interest1).first;
-  pitEntry->insertOrUpdateInRecord(*face1, *interest1);
-  pitEntry->insertOrUpdateInRecord(*face2, *interest2);
-  pitEntry->insertOrUpdateOutRecord(*face3, *interest1);
-
-  lp::Nack nack3 = makeNack("/McQYjMbm", 992, lp::NackReason::CONGESTION);
-  pitEntry->getOutRecord(*face3)->setIncomingNack(nack3);
-  strategy.afterReceiveNack(*face3, nack3, pitEntry);
-
-  BOOST_REQUIRE_EQUAL(strategy.sendNackHistory.size(), 2);
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[0].pitInterest, pitEntry->getInterest());
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[0].header.getReason(), lp::NackReason::CONGESTION);
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[1].pitInterest, pitEntry->getInterest());
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[1].header.getReason(), lp::NackReason::CONGESTION);
-  std::unordered_set<FaceId> nackFaceIds{strategy.sendNackHistory[0].outFaceId,
-                                         strategy.sendNackHistory[1].outFaceId};
-  std::unordered_set<FaceId> expectedNackFaceIds{face1->getId(), face2->getId()};
-  BOOST_CHECK_EQUAL_COLLECTIONS(nackFaceIds.begin(), nackFaceIds.end(),
-                                expectedNackFaceIds.begin(), expectedNackFaceIds.end());
-}
-
-BOOST_AUTO_TEST_CASE(TwoUpstreams) // two upstreams, send Nack when both Nacks arrive
-{
-  fib::Entry& fibEntry = *fib.insert(Name()).first;
-  fibEntry.addNextHop(*face3, 10);
-  fibEntry.addNextHop(*face4, 20);
-  fibEntry.addNextHop(*face5, 30);
-
-  shared_ptr<Interest> interest1 = makeInterest("/aS9FAyUV19", 286);
-  shared_ptr<pit::Entry> pitEntry = pit.insert(*interest1).first;
-  pitEntry->insertOrUpdateInRecord(*face1, *interest1);
-  pitEntry->insertOrUpdateOutRecord(*face3, *interest1);
-  pitEntry->insertOrUpdateOutRecord(*face4, *interest1);
-
-  lp::Nack nack3 = makeNack("/aS9FAyUV19", 286, lp::NackReason::CONGESTION);
-  pitEntry->getOutRecord(*face3)->setIncomingNack(nack3);
-  strategy.afterReceiveNack(*face3, nack3, pitEntry);
-
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory.size(), 0); // don't send Nack until all upstreams have Nacked
-
-  lp::Nack nack4 = makeNack("/aS9FAyUV19", 286, lp::NackReason::CONGESTION);
-  pitEntry->getOutRecord(*face4)->setIncomingNack(nack4);
-  strategy.afterReceiveNack(*face4, nack4, pitEntry);
-
-  BOOST_REQUIRE_EQUAL(strategy.sendNackHistory.size(), 1);
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[0].pitInterest, pitEntry->getInterest());
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[0].outFaceId, face1->getId());
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[0].header.getReason(), lp::NackReason::CONGESTION);
-}
-
-BOOST_AUTO_TEST_CASE(Timeout) // two upstreams, one times out, don't send Nack
-{
-  fib::Entry& fibEntry = *fib.insert(Name()).first;
-  fibEntry.addNextHop(*face3, 10);
-  fibEntry.addNextHop(*face4, 20);
-  fibEntry.addNextHop(*face5, 30);
-
-  shared_ptr<Interest> interest1 = makeInterest("/sIYw0TXWDj", 115);
-  interest1->setInterestLifetime(time::milliseconds(400));
-  shared_ptr<pit::Entry> pitEntry = pit.insert(*interest1).first;
-  pitEntry->insertOrUpdateInRecord(*face1, *interest1);
-  pitEntry->insertOrUpdateOutRecord(*face3, *interest1);
-
-  this->advanceClocks(time::milliseconds(300));
-  shared_ptr<Interest> interest2 = makeInterest("/sIYw0TXWDj", 223);
-  pitEntry->insertOrUpdateInRecord(*face1, *interest2);
-  pitEntry->insertOrUpdateOutRecord(*face4, *interest2);
-
-  this->advanceClocks(time::milliseconds(200)); // face3 has timed out
-
-  lp::Nack nack4 = makeNack("/sIYw0TXWDj", 223, lp::NackReason::CONGESTION);
-  pitEntry->getOutRecord(*face4)->setIncomingNack(nack4);
-  strategy.afterReceiveNack(*face4, nack4, pitEntry);
-
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory.size(), 0);
-}
-
-BOOST_FIXTURE_TEST_CASE(LiveDeadlock, UnitTestTimeFixture) // #3033 note-7
-{
-  /*
-   *           /----------\
-   *           | producer |
-   *           \----------/
-   *                |
-   *              +---+
-   *              | P |
-   *              +---+
-   *                |
-   *           failed link
-   *                |
-   *              +---+
-   *              | R |
-   *              +---+
-   *             ^     ^
-   *            /       \
-   *           /         \
-   *        +---+       +---+
-   *        | B | <---> | C |
-   *        +---+       +---+
-   *          ^           ^
-   *          |           |
-   *          |           |
-   *        +---+       +---+
-   *        | A |       | D |
-   *        +---+       +---+
-   *          ^           ^
-   *          |           |
-   *  /----------\     /----------\
-   *  | consumer |     | consumer |
-   *  \----------/     \----------/
-   */
-
-  TopologyTester topo;
-  TopologyNode nodeP = topo.addForwarder("P"),
-               nodeR = topo.addForwarder("R"),
-               nodeA = topo.addForwarder("A"),
-               nodeB = topo.addForwarder("B"),
-               nodeC = topo.addForwarder("C"),
-               nodeD = topo.addForwarder("D");
-
-  for (TopologyNode node : {nodeP, nodeR, nodeA, nodeB, nodeC, nodeD}) {
-    topo.setStrategy<BestRouteStrategy2>(node);
-  }
-
-  const time::milliseconds LINK_DELAY(10);
-  shared_ptr<TopologyLink> linkPR = topo.addLink("PR", LINK_DELAY, {nodeP, nodeR}),
-                           linkRB = topo.addLink("RB", LINK_DELAY, {nodeR, nodeB}),
-                           linkRC = topo.addLink("RC", LINK_DELAY, {nodeR, nodeC}),
-                           linkBC = topo.addLink("BC", LINK_DELAY, {nodeB, nodeC}),
-                           linkBA = topo.addLink("BA", LINK_DELAY, {nodeB, nodeA}),
-                           linkCD = topo.addLink("CD", LINK_DELAY, {nodeC, nodeD});
-
-  // TODO register the prefix on R->P but then set the face DOWN
-  // topo.registerPrefix(nodeR, linkPR->getFace(nodeR), "ndn:/P", 10);
-  topo.registerPrefix(nodeB, linkRB->getFace(nodeB), "ndn:/P", 20);
-  topo.registerPrefix(nodeB, linkBC->getFace(nodeB), "ndn:/P", 30);
-  topo.registerPrefix(nodeC, linkRC->getFace(nodeC), "ndn:/P", 20);
-  topo.registerPrefix(nodeC, linkBC->getFace(nodeC), "ndn:/P", 30);
-  topo.registerPrefix(nodeA, linkBA->getFace(nodeA), "ndn:/P", 30);
-  topo.registerPrefix(nodeD, linkCD->getFace(nodeD), "ndn:/P", 30);
-
-  ndn::Face& appA = topo.addAppFace("A", nodeA)->getClientFace();
-  ndn::Face& appD = topo.addAppFace("D", nodeD)->getClientFace();
-
-  int nNacksA = 0, nNacksD = 0;
-  appA.expressInterest(Interest("/P/1"), bind([]{}), bind([&nNacksA]{ ++nNacksA; }), bind([]{}));
-  appD.expressInterest(Interest("/P/1"), bind([]{}), bind([&nNacksD]{ ++nNacksD; }), bind([]{}));
-  this->advanceClocks(time::milliseconds(1), time::milliseconds(5));
-  appA.expressInterest(Interest("/P/1"), bind([]{}), bind([&nNacksA]{ ++nNacksA; }), bind([]{}));
-  appD.expressInterest(Interest("/P/1"), bind([]{}), bind([&nNacksD]{ ++nNacksD; }), bind([]{}));
-  this->advanceClocks(time::milliseconds(1), time::milliseconds(100));
-
-  // As long as at least one Nack arrives at each client, strategy behavior is correct.
-  // Whether both Interests are Nacked is a client face behavior, not strategy behavior.
-  BOOST_CHECK_GT(nNacksA, 0);
-  BOOST_CHECK_GT(nNacksD, 0);
-}
-
-template<lp::NackReason X, lp::NackReason Y, lp::NackReason R>
-struct NackReasonCombination
-{
-  lp::NackReason
-  getX() const
-  {
-    return X;
-  }
-
-  lp::NackReason
-  getY() const
-  {
-    return Y;
-  }
-
-  lp::NackReason
-  getExpectedResult() const
-  {
-    return R;
-  }
-};
-
-typedef boost::mpl::vector<
-    NackReasonCombination<lp::NackReason::CONGESTION, lp::NackReason::CONGESTION, lp::NackReason::CONGESTION>,
-    NackReasonCombination<lp::NackReason::CONGESTION, lp::NackReason::DUPLICATE, lp::NackReason::CONGESTION>,
-    NackReasonCombination<lp::NackReason::CONGESTION, lp::NackReason::NO_ROUTE, lp::NackReason::CONGESTION>,
-    NackReasonCombination<lp::NackReason::DUPLICATE, lp::NackReason::CONGESTION, lp::NackReason::CONGESTION>,
-    NackReasonCombination<lp::NackReason::DUPLICATE, lp::NackReason::DUPLICATE, lp::NackReason::DUPLICATE>,
-    NackReasonCombination<lp::NackReason::DUPLICATE, lp::NackReason::NO_ROUTE, lp::NackReason::DUPLICATE>,
-    NackReasonCombination<lp::NackReason::NO_ROUTE, lp::NackReason::CONGESTION, lp::NackReason::CONGESTION>,
-    NackReasonCombination<lp::NackReason::NO_ROUTE, lp::NackReason::DUPLICATE, lp::NackReason::DUPLICATE>,
-    NackReasonCombination<lp::NackReason::NO_ROUTE, lp::NackReason::NO_ROUTE, lp::NackReason::NO_ROUTE>
-  > NackReasonCombinations;
-
-BOOST_AUTO_TEST_CASE_TEMPLATE(CombineReasons, Combination, NackReasonCombinations)
-{
-  Combination combination;
-
-  fib::Entry& fibEntry = *fib.insert(Name()).first;
-  fibEntry.addNextHop(*face3, 10);
-  fibEntry.addNextHop(*face4, 20);
-  fibEntry.addNextHop(*face5, 30);
-
-  shared_ptr<Interest> interest1 = makeInterest("/F6sEwB24I", 282);
-  shared_ptr<pit::Entry> pitEntry = pit.insert(*interest1).first;
-  pitEntry->insertOrUpdateInRecord(*face1, *interest1);
-  pitEntry->insertOrUpdateOutRecord(*face3, *interest1);
-  pitEntry->insertOrUpdateOutRecord(*face4, *interest1);
-
-  lp::Nack nack3 = makeNack("/F6sEwB24I", 282, combination.getX());
-  pitEntry->getOutRecord(*face3)->setIncomingNack(nack3);
-  strategy.afterReceiveNack(*face3, nack3, pitEntry);
-
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory.size(), 0);
-
-  lp::Nack nack4 = makeNack("/F6sEwB24I", 282, combination.getY());
-  pitEntry->getOutRecord(*face4)->setIncomingNack(nack4);
-  strategy.afterReceiveNack(*face4, nack4, pitEntry);
-
-  BOOST_REQUIRE_EQUAL(strategy.sendNackHistory.size(), 1);
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[0].pitInterest, pitEntry->getInterest());
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[0].outFaceId, face1->getId());
-  BOOST_CHECK_EQUAL(strategy.sendNackHistory[0].header.getReason(), combination.getExpectedResult());
-}
-
-BOOST_AUTO_TEST_SUITE_END() // IncomingNack
-
 BOOST_AUTO_TEST_SUITE_END() // TestBestRouteStrategy2
 BOOST_AUTO_TEST_SUITE_END() // Fw