table+fw: move forwarding semantics out of PIT entry

refs #3546

Change-Id: I1e6f87fd81176c116b6d758156da1cf96ea03608
diff --git a/tests/daemon/fw/pit-algorithm.t.cpp b/tests/daemon/fw/pit-algorithm.t.cpp
new file mode 100644
index 0000000..239823c
--- /dev/null
+++ b/tests/daemon/fw/pit-algorithm.t.cpp
@@ -0,0 +1,203 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2016,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "fw/pit-algorithm.hpp"
+
+#include "tests/test-common.hpp"
+#include "tests/daemon/face/dummy-face.hpp"
+
+namespace nfd {
+namespace fw {
+namespace tests {
+
+using namespace nfd::tests;
+
+BOOST_AUTO_TEST_SUITE(Fw)
+BOOST_FIXTURE_TEST_SUITE(TestPitAlgorithm, BaseFixture)
+
+class ScopeControlFixture : public BaseFixture
+{
+protected:
+  ScopeControlFixture()
+    : nonLocalFace1(make_shared<DummyFace>("dummy://1", "dummy://1", ndn::nfd::FACE_SCOPE_NON_LOCAL))
+    , nonLocalFace2(make_shared<DummyFace>("dummy://2", "dummy://2", ndn::nfd::FACE_SCOPE_NON_LOCAL))
+    , localFace3(make_shared<DummyFace>("dummy://3", "dummy://3", ndn::nfd::FACE_SCOPE_LOCAL))
+    , localFace4(make_shared<DummyFace>("dummy://4", "dummy://4", ndn::nfd::FACE_SCOPE_LOCAL))
+  {
+  }
+
+protected:
+  shared_ptr<Face> nonLocalFace1;
+  shared_ptr<Face> nonLocalFace2;
+  shared_ptr<Face> localFace3;
+  shared_ptr<Face> localFace4;
+};
+
+BOOST_FIXTURE_TEST_SUITE(ViolatesScope, ScopeControlFixture)
+
+BOOST_AUTO_TEST_CASE(Unrestricted)
+{
+  shared_ptr<Interest> interest = makeInterest("ndn:/ieWRzDsCu");
+  pit::Entry entry(*interest);
+
+  entry.insertOrUpdateInRecord(nonLocalFace1, *interest);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *nonLocalFace2), false);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *localFace4), false);
+}
+
+BOOST_AUTO_TEST_CASE(Localhost)
+{
+  shared_ptr<Interest> interest = makeInterest("ndn:/localhost/5n1LzIt3");
+  pit::Entry entry(*interest);
+
+  entry.insertOrUpdateInRecord(localFace3, *interest);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *nonLocalFace2), true);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *localFace4), false);
+}
+
+BOOST_AUTO_TEST_CASE(LocalhopFromLocal)
+{
+  shared_ptr<Interest> interest = makeInterest("ndn:/localhop/YcIKWCRYJ");
+  pit::Entry entry(*interest);
+
+  entry.insertOrUpdateInRecord(localFace3, *interest);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *nonLocalFace2), false);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *localFace4), false);
+}
+
+BOOST_AUTO_TEST_CASE(LocalhopFromNonLocal)
+{
+  shared_ptr<Interest> interest = makeInterest("ndn:/localhop/x5uFr5IpqY");
+  pit::Entry entry(*interest);
+
+  entry.insertOrUpdateInRecord(nonLocalFace1, *interest);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *nonLocalFace2), true);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *localFace4), false);
+}
+
+BOOST_AUTO_TEST_CASE(LocalhopFromLocalAndNonLocal)
+{
+  shared_ptr<Interest> interest = makeInterest("ndn:/localhop/gNn2MJAXt");
+  pit::Entry entry(*interest);
+
+  entry.insertOrUpdateInRecord(nonLocalFace1, *interest);
+  entry.insertOrUpdateInRecord(localFace3, *interest);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *nonLocalFace2), false);
+  BOOST_CHECK_EQUAL(violatesScope(entry, *localFace4), false);
+}
+
+BOOST_AUTO_TEST_SUITE_END() // ViolatesScope
+
+BOOST_AUTO_TEST_CASE(CanForwardToLegacy)
+{
+  shared_ptr<Interest> interest = makeInterest("ndn:/WDsuBLIMG");
+  pit::Entry entry(*interest);
+
+  auto face1 = make_shared<DummyFace>();
+  auto face2 = make_shared<DummyFace>();
+
+  entry.insertOrUpdateInRecord(face1, *interest);
+  BOOST_CHECK_EQUAL(canForwardToLegacy(entry, *face1), false);
+  BOOST_CHECK_EQUAL(canForwardToLegacy(entry, *face2), true);
+
+  entry.insertOrUpdateInRecord(face2, *interest);
+  BOOST_CHECK_EQUAL(canForwardToLegacy(entry, *face1), true);
+  BOOST_CHECK_EQUAL(canForwardToLegacy(entry, *face2), true);
+
+  entry.insertOrUpdateOutRecord(face1, *interest);
+  BOOST_CHECK_EQUAL(canForwardToLegacy(entry, *face1), false);
+  BOOST_CHECK_EQUAL(canForwardToLegacy(entry, *face2), true);
+}
+
+BOOST_AUTO_TEST_CASE(Nonce)
+{
+  auto face1 = make_shared<DummyFace>();
+  auto face2 = make_shared<DummyFace>();
+
+  shared_ptr<Interest> interest = makeInterest("ndn:/qtCQ7I1c");
+  interest->setNonce(25559);
+
+  pit::Entry entry0(*interest);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry0, 25559, *face1), DUPLICATE_NONCE_NONE);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry0, 25559, *face2), DUPLICATE_NONCE_NONE);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry0, 19004, *face1), DUPLICATE_NONCE_NONE);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry0, 19004, *face2), DUPLICATE_NONCE_NONE);
+
+  pit::Entry entry1(*interest);
+  entry1.insertOrUpdateInRecord(face1, *interest);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry1, 25559, *face1), DUPLICATE_NONCE_IN_SAME);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry1, 25559, *face2), DUPLICATE_NONCE_IN_OTHER);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry1, 19004, *face1), DUPLICATE_NONCE_NONE);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry1, 19004, *face2), DUPLICATE_NONCE_NONE);
+
+  pit::Entry entry2(*interest);
+  entry2.insertOrUpdateOutRecord(face1, *interest);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry2, 25559, *face1), DUPLICATE_NONCE_OUT_SAME);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry2, 25559, *face2), DUPLICATE_NONCE_OUT_OTHER);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry2, 19004, *face1), DUPLICATE_NONCE_NONE);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry2, 19004, *face2), DUPLICATE_NONCE_NONE);
+
+  pit::Entry entry3(*interest);
+  entry3.insertOrUpdateInRecord(face1, *interest);
+  entry3.insertOrUpdateOutRecord(face1, *interest);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry3, 25559, *face1),
+                    DUPLICATE_NONCE_IN_SAME | DUPLICATE_NONCE_OUT_SAME);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry3, 25559, *face2),
+                    DUPLICATE_NONCE_IN_OTHER | DUPLICATE_NONCE_OUT_OTHER);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry3, 19004, *face1), DUPLICATE_NONCE_NONE);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry3, 19004, *face2), DUPLICATE_NONCE_NONE);
+
+  pit::Entry entry4(*interest);
+  entry4.insertOrUpdateInRecord(face1, *interest);
+  entry4.insertOrUpdateInRecord(face2, *interest);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry4, 25559, *face1),
+                    DUPLICATE_NONCE_IN_SAME | DUPLICATE_NONCE_IN_OTHER);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry4, 25559, *face2),
+                    DUPLICATE_NONCE_IN_SAME | DUPLICATE_NONCE_IN_OTHER);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry4, 19004, *face1), DUPLICATE_NONCE_NONE);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry4, 19004, *face2), DUPLICATE_NONCE_NONE);
+
+  pit::Entry entry5(*interest);
+  entry5.insertOrUpdateOutRecord(face1, *interest);
+  entry5.insertOrUpdateOutRecord(face2, *interest);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry5, 25559, *face1),
+                    DUPLICATE_NONCE_OUT_SAME | DUPLICATE_NONCE_OUT_OTHER);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry5, 25559, *face2),
+                    DUPLICATE_NONCE_OUT_SAME | DUPLICATE_NONCE_OUT_OTHER);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry5, 19004, *face1), DUPLICATE_NONCE_NONE);
+  BOOST_CHECK_EQUAL(findDuplicateNonce(entry5, 19004, *face2), DUPLICATE_NONCE_NONE);
+}
+
+BOOST_AUTO_TEST_CASE(HasPendingOutRecords)
+{
+  /// \todo #3545
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestPitAlgorithm
+BOOST_AUTO_TEST_SUITE_END() // Fw
+
+} // namespace tests
+} // namespace fw
+} // namespace nfd
diff --git a/tests/daemon/table/pit.t.cpp b/tests/daemon/table/pit.t.cpp
index 546c0a5..9ca3ec7 100644
--- a/tests/daemon/table/pit.t.cpp
+++ b/tests/daemon/table/pit.t.cpp
@@ -154,65 +154,6 @@
   BOOST_CHECK(entry.getOutRecord(*face2) == entry.getOutRecords().end());
 }
 
-BOOST_AUTO_TEST_CASE(Nonce)
-{
-  shared_ptr<Face> face1 = make_shared<DummyFace>();
-  shared_ptr<Face> face2 = make_shared<DummyFace>();
-
-  shared_ptr<Interest> interest = makeInterest("ndn:/qtCQ7I1c");
-  interest->setNonce(25559);
-
-  pit::Entry entry0(*interest);
-  BOOST_CHECK_EQUAL(entry0.findNonce(25559, *face1), pit::DUPLICATE_NONCE_NONE);
-  BOOST_CHECK_EQUAL(entry0.findNonce(25559, *face2), pit::DUPLICATE_NONCE_NONE);
-  BOOST_CHECK_EQUAL(entry0.findNonce(19004, *face1), pit::DUPLICATE_NONCE_NONE);
-  BOOST_CHECK_EQUAL(entry0.findNonce(19004, *face2), pit::DUPLICATE_NONCE_NONE);
-
-  pit::Entry entry1(*interest);
-  entry1.insertOrUpdateInRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(entry1.findNonce(25559, *face1), pit::DUPLICATE_NONCE_IN_SAME);
-  BOOST_CHECK_EQUAL(entry1.findNonce(25559, *face2), pit::DUPLICATE_NONCE_IN_OTHER);
-  BOOST_CHECK_EQUAL(entry1.findNonce(19004, *face1), pit::DUPLICATE_NONCE_NONE);
-  BOOST_CHECK_EQUAL(entry1.findNonce(19004, *face2), pit::DUPLICATE_NONCE_NONE);
-
-  pit::Entry entry2(*interest);
-  entry2.insertOrUpdateOutRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(entry2.findNonce(25559, *face1), pit::DUPLICATE_NONCE_OUT_SAME);
-  BOOST_CHECK_EQUAL(entry2.findNonce(25559, *face2), pit::DUPLICATE_NONCE_OUT_OTHER);
-  BOOST_CHECK_EQUAL(entry2.findNonce(19004, *face1), pit::DUPLICATE_NONCE_NONE);
-  BOOST_CHECK_EQUAL(entry2.findNonce(19004, *face2), pit::DUPLICATE_NONCE_NONE);
-
-  pit::Entry entry3(*interest);
-  entry3.insertOrUpdateInRecord(face1, *interest);
-  entry3.insertOrUpdateOutRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(entry3.findNonce(25559, *face1),
-                    pit::DUPLICATE_NONCE_IN_SAME | pit::DUPLICATE_NONCE_OUT_SAME);
-  BOOST_CHECK_EQUAL(entry3.findNonce(25559, *face2),
-                    pit::DUPLICATE_NONCE_IN_OTHER | pit::DUPLICATE_NONCE_OUT_OTHER);
-  BOOST_CHECK_EQUAL(entry3.findNonce(19004, *face1), pit::DUPLICATE_NONCE_NONE);
-  BOOST_CHECK_EQUAL(entry3.findNonce(19004, *face2), pit::DUPLICATE_NONCE_NONE);
-
-  pit::Entry entry4(*interest);
-  entry4.insertOrUpdateInRecord(face1, *interest);
-  entry4.insertOrUpdateInRecord(face2, *interest);
-  BOOST_CHECK_EQUAL(entry4.findNonce(25559, *face1),
-                    pit::DUPLICATE_NONCE_IN_SAME | pit::DUPLICATE_NONCE_IN_OTHER);
-  BOOST_CHECK_EQUAL(entry4.findNonce(25559, *face2),
-                    pit::DUPLICATE_NONCE_IN_SAME | pit::DUPLICATE_NONCE_IN_OTHER);
-  BOOST_CHECK_EQUAL(entry4.findNonce(19004, *face1), pit::DUPLICATE_NONCE_NONE);
-  BOOST_CHECK_EQUAL(entry4.findNonce(19004, *face2), pit::DUPLICATE_NONCE_NONE);
-
-  pit::Entry entry5(*interest);
-  entry5.insertOrUpdateOutRecord(face1, *interest);
-  entry5.insertOrUpdateOutRecord(face2, *interest);
-  BOOST_CHECK_EQUAL(entry5.findNonce(25559, *face1),
-                    pit::DUPLICATE_NONCE_OUT_SAME | pit::DUPLICATE_NONCE_OUT_OTHER);
-  BOOST_CHECK_EQUAL(entry5.findNonce(25559, *face2),
-                    pit::DUPLICATE_NONCE_OUT_SAME | pit::DUPLICATE_NONCE_OUT_OTHER);
-  BOOST_CHECK_EQUAL(entry5.findNonce(19004, *face1), pit::DUPLICATE_NONCE_NONE);
-  BOOST_CHECK_EQUAL(entry5.findNonce(19004, *face2), pit::DUPLICATE_NONCE_NONE);
-}
-
 BOOST_AUTO_TEST_CASE(Lifetime)
 {
   shared_ptr<Interest> interest = makeInterest("ndn:/7oIEurbgy6");
@@ -229,27 +170,6 @@
   BOOST_CHECK_GT(outIt->getExpiry(), time::steady_clock::now());
 }
 
-BOOST_AUTO_TEST_CASE(CanForwardTo)
-{
-  shared_ptr<Interest> interest = makeInterest("ndn:/WDsuBLIMG");
-  pit::Entry entry(*interest);
-
-  shared_ptr<Face> face1 = make_shared<DummyFace>();
-  shared_ptr<Face> face2 = make_shared<DummyFace>();
-
-  entry.insertOrUpdateInRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(entry.canForwardTo(*face1), false);
-  BOOST_CHECK_EQUAL(entry.canForwardTo(*face2), true);
-
-  entry.insertOrUpdateInRecord(face2, *interest);
-  BOOST_CHECK_EQUAL(entry.canForwardTo(*face1), true);
-  BOOST_CHECK_EQUAL(entry.canForwardTo(*face2), true);
-
-  entry.insertOrUpdateOutRecord(face1, *interest);
-  BOOST_CHECK_EQUAL(entry.canForwardTo(*face1), false);
-  BOOST_CHECK_EQUAL(entry.canForwardTo(*face2), true);
-}
-
 BOOST_AUTO_TEST_CASE(OutRecordNack)
 {
   shared_ptr<Face> face1 = make_shared<DummyFace>();