src: Reorganizing source code in preparation to merge NRD code
Note that as of this commit, there are several changes in location of
compiled binaries in `build/` folder:
* `nfd` has been moved to `build/bin/nfd`
* `unit-tests` has been split into `unit-tests-core` and `unit-tests-daemon`
Change-Id: I2c830c117879edbaa5457d6423c13f0273285919
Refs: #1486
diff --git a/tests/daemon/mgmt/fib-manager.cpp b/tests/daemon/mgmt/fib-manager.cpp
new file mode 100644
index 0000000..b38c3b8
--- /dev/null
+++ b/tests/daemon/mgmt/fib-manager.cpp
@@ -0,0 +1,920 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014 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
+ *
+ * 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 "mgmt/fib-manager.hpp"
+#include "table/fib.hpp"
+#include "table/fib-nexthop.hpp"
+#include "face/face.hpp"
+#include "mgmt/internal-face.hpp"
+#include "tests/daemon/face/dummy-face.hpp"
+
+#include "validation-common.hpp"
+#include "tests/test-common.hpp"
+
+#include "fib-enumeration-publisher-common.hpp"
+
+namespace nfd {
+namespace tests {
+
+NFD_LOG_INIT("FibManagerTest");
+
+class FibManagerFixture : public FibEnumerationPublisherFixture
+{
+public:
+
+ virtual
+ ~FibManagerFixture()
+ {
+ }
+
+ shared_ptr<Face>
+ getFace(FaceId id)
+ {
+ if (id > 0 && static_cast<size_t>(id) <= m_faces.size())
+ {
+ return m_faces[id - 1];
+ }
+ NFD_LOG_DEBUG("No face found returning NULL");
+ return shared_ptr<DummyFace>();
+ }
+
+ void
+ addFace(shared_ptr<Face> face)
+ {
+ m_faces.push_back(face);
+ }
+
+ void
+ validateControlResponseCommon(const Data& response,
+ const Name& expectedName,
+ uint32_t expectedCode,
+ const std::string& expectedText,
+ ControlResponse& control)
+ {
+ m_callbackFired = true;
+ Block controlRaw = response.getContent().blockFromValue();
+
+ control.wireDecode(controlRaw);
+
+ // NFD_LOG_DEBUG("received control response"
+ // << " Name: " << response.getName()
+ // << " code: " << control.getCode()
+ // << " text: " << control.getText());
+
+ BOOST_CHECK_EQUAL(response.getName(), expectedName);
+ BOOST_CHECK_EQUAL(control.getCode(), expectedCode);
+ BOOST_CHECK_EQUAL(control.getText(), expectedText);
+ }
+
+ void
+ validateControlResponse(const Data& response,
+ const Name& expectedName,
+ uint32_t expectedCode,
+ const std::string& expectedText)
+ {
+ ControlResponse control;
+ validateControlResponseCommon(response, expectedName,
+ expectedCode, expectedText, control);
+
+ if (!control.getBody().empty())
+ {
+ BOOST_FAIL("found unexpected control response body");
+ }
+ }
+
+ void
+ validateControlResponse(const Data& response,
+ const Name& expectedName,
+ uint32_t expectedCode,
+ const std::string& expectedText,
+ const Block& expectedBody)
+ {
+ ControlResponse control;
+ validateControlResponseCommon(response, expectedName,
+ expectedCode, expectedText, control);
+
+ BOOST_REQUIRE(!control.getBody().empty());
+ BOOST_REQUIRE_EQUAL(control.getBody().value_size(), expectedBody.value_size());
+
+ BOOST_CHECK(memcmp(control.getBody().value(), expectedBody.value(),
+ expectedBody.value_size()) == 0);
+
+ }
+
+ bool
+ didCallbackFire()
+ {
+ return m_callbackFired;
+ }
+
+ void
+ resetCallbackFired()
+ {
+ m_callbackFired = false;
+ }
+
+ shared_ptr<InternalFace>
+ getInternalFace()
+ {
+ return m_face;
+ }
+
+ FibManager&
+ getFibManager()
+ {
+ return m_manager;
+ }
+
+ Fib&
+ getFib()
+ {
+ return m_fib;
+ }
+
+ void
+ addInterestRule(const std::string& regex,
+ ndn::IdentityCertificate& certificate)
+ {
+ m_manager.addInterestRule(regex, certificate);
+ }
+
+protected:
+ FibManagerFixture()
+ : m_manager(boost::ref(m_fib),
+ bind(&FibManagerFixture::getFace, this, _1),
+ m_face)
+ , m_callbackFired(false)
+ {
+ }
+
+protected:
+ FibManager m_manager;
+
+ std::vector<shared_ptr<Face> > m_faces;
+ bool m_callbackFired;
+};
+
+template <typename T> class AuthorizedCommandFixture:
+ public CommandFixture<T>
+{
+public:
+ AuthorizedCommandFixture()
+ {
+ const std::string regex = "^<localhost><nfd><fib>";
+ T::addInterestRule(regex, *CommandFixture<T>::m_certificate);
+ }
+
+ virtual
+ ~AuthorizedCommandFixture()
+ {
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(MgmtFibManager, AuthorizedCommandFixture<FibManagerFixture>)
+
+bool
+foundNextHop(FaceId id, uint32_t cost, const fib::NextHop& next)
+{
+ return id == next.getFace()->getId() && next.getCost() == cost;
+}
+
+bool
+addedNextHopWithCost(const Fib& fib, const Name& prefix, size_t oldSize, uint32_t cost)
+{
+ shared_ptr<fib::Entry> entry = fib.findExactMatch(prefix);
+
+ if (static_cast<bool>(entry))
+ {
+ const fib::NextHopList& hops = entry->getNextHops();
+ return hops.size() == oldSize + 1 &&
+ std::find_if(hops.begin(), hops.end(), bind(&foundNextHop, -1, cost, _1)) != hops.end();
+ }
+ return false;
+}
+
+bool
+foundNextHopWithFace(FaceId id, uint32_t cost,
+ shared_ptr<Face> face, const fib::NextHop& next)
+{
+ return id == next.getFace()->getId() && next.getCost() == cost && face == next.getFace();
+}
+
+bool
+addedNextHopWithFace(const Fib& fib, const Name& prefix, size_t oldSize,
+ uint32_t cost, shared_ptr<Face> face)
+{
+ shared_ptr<fib::Entry> entry = fib.findExactMatch(prefix);
+
+ if (static_cast<bool>(entry))
+ {
+ const fib::NextHopList& hops = entry->getNextHops();
+ return hops.size() == oldSize + 1 &&
+ std::find_if(hops.begin(), hops.end(), bind(&foundNextHop, -1, cost, _1)) != hops.end();
+ }
+ return false;
+}
+
+BOOST_AUTO_TEST_CASE(TestFireInterestFilter)
+{
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ shared_ptr<Interest> command = makeInterest("/localhost/nfd/fib");
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 400, "Malformed command");
+
+ face->sendInterest(*command);
+ g_io.run_one();
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(MalformedCommmand)
+{
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ BOOST_REQUIRE(didCallbackFire() == false);
+
+ Interest command("/localhost/nfd/fib");
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command.getName(), 400, "Malformed command");
+
+ getFibManager().onFibRequest(command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(UnsupportedVerb)
+{
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+ parameters.setCost(1);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("unsupported");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 501, "Unsupported command");
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(UnsignedCommand)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+ parameters.setCost(101);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ Interest command(commandName);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse,
+ this, _1, command.getName(), 401, "Signature required");
+
+
+ getFibManager().onFibRequest(command);
+
+ BOOST_REQUIRE(didCallbackFire());
+ BOOST_REQUIRE(!addedNextHopWithCost(getFib(), "/hello", 0, 101));
+}
+
+BOOST_FIXTURE_TEST_CASE(UnauthorizedCommand, UnauthorizedCommandFixture<FibManagerFixture>)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+ parameters.setCost(101);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse,
+ this, _1, command->getName(), 403, "Unauthorized command");
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+ BOOST_REQUIRE(!addedNextHopWithCost(getFib(), "/hello", 0, 101));
+}
+
+BOOST_AUTO_TEST_CASE(BadOptionParse)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append("NotReallyParameters");
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 400, "Malformed command");
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(UnknownFaceId)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1000);
+ parameters.setCost(101);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 410, "Face not found");
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+ BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 101) == false);
+}
+
+BOOST_AUTO_TEST_CASE(TestImplicitFaceId)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(0);
+ parameters.setCost(101);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ ControlParameters expectedParameters;
+ expectedParameters.setName("/hello");
+ expectedParameters.setFaceId(1);
+ expectedParameters.setCost(101);
+
+ Block encodedExpectedParameters(expectedParameters.wireEncode());
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ command->setIncomingFaceId(1);
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 200, "Success", encodedExpectedParameters);
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+ BOOST_REQUIRE(addedNextHopWithFace(getFib(), "/hello", 0, 101, getFace(1)));
+}
+
+BOOST_AUTO_TEST_CASE(AddNextHopVerbInitialAdd)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+ parameters.setCost(101);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 200, "Success", encodedParameters);
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+ BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 101));
+}
+
+BOOST_AUTO_TEST_CASE(AddNextHopVerbImplicitCost)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ ControlParameters resultParameters;
+ resultParameters.setName("/hello");
+ resultParameters.setFaceId(1);
+ resultParameters.setCost(0);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 200, "Success", resultParameters.wireEncode());
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+ BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 0));
+}
+
+BOOST_AUTO_TEST_CASE(AddNextHopVerbAddToExisting)
+{
+ addFace(make_shared<DummyFace>());
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ for (int i = 1; i <= 2; i++)
+ {
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+ parameters.setCost(100 + i);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 200, "Success", encodedParameters);
+
+ getFibManager().onFibRequest(*command);
+ BOOST_REQUIRE(didCallbackFire());
+ resetCallbackFired();
+
+ shared_ptr<fib::Entry> entry = getFib().findExactMatch("/hello");
+
+ if (static_cast<bool>(entry))
+ {
+ const fib::NextHopList& hops = entry->getNextHops();
+ BOOST_REQUIRE(hops.size() == 1);
+ BOOST_REQUIRE(std::find_if(hops.begin(), hops.end(),
+ bind(&foundNextHop, -1, 100 + i, _1)) != hops.end());
+
+ }
+ else
+ {
+ BOOST_FAIL("Failed to find expected fib entry");
+ }
+
+ face->onReceiveData.clear();
+ }
+}
+
+BOOST_AUTO_TEST_CASE(AddNextHopVerbUpdateFaceCost)
+{
+ addFace(make_shared<DummyFace>());
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+
+ {
+ parameters.setCost(1);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 200, "Success", encodedParameters);
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+ }
+
+ resetCallbackFired();
+ face->onReceiveData.clear();
+
+ {
+ parameters.setCost(102);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 200, "Success", encodedParameters);
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+ }
+
+ shared_ptr<fib::Entry> entry = getFib().findExactMatch("/hello");
+
+ // Add faces with cost == FaceID for the name /hello
+ // This test assumes:
+ // FaceIDs are -1 because we don't add them to a forwarder
+ if (static_cast<bool>(entry))
+ {
+ const fib::NextHopList& hops = entry->getNextHops();
+ BOOST_REQUIRE(hops.size() == 1);
+ BOOST_REQUIRE(std::find_if(hops.begin(),
+ hops.end(),
+ bind(&foundNextHop, -1, 102, _1)) != hops.end());
+ }
+ else
+ {
+ BOOST_FAIL("Failed to find expected fib entry");
+ }
+}
+
+BOOST_AUTO_TEST_CASE(AddNextHopVerbMissingPrefix)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setFaceId(1);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 400, "Malformed command");
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(AddNextHopVerbMissingFaceId)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("add-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 400, "Malformed command");
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+bool
+removedNextHopWithCost(const Fib& fib, const Name& prefix, size_t oldSize, uint32_t cost)
+{
+ shared_ptr<fib::Entry> entry = fib.findExactMatch(prefix);
+
+ if (static_cast<bool>(entry))
+ {
+ const fib::NextHopList& hops = entry->getNextHops();
+ return hops.size() == oldSize - 1 &&
+ std::find_if(hops.begin(), hops.end(), bind(&foundNextHop, -1, cost, _1)) == hops.end();
+ }
+ return false;
+}
+
+void
+testRemoveNextHop(CommandFixture<FibManagerFixture>* fixture,
+ FibManager& manager,
+ Fib& fib,
+ shared_ptr<Face> face,
+ const Name& targetName,
+ FaceId targetFace)
+{
+ ControlParameters parameters;
+ parameters.setName(targetName);
+ parameters.setFaceId(targetFace);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("remove-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ fixture->generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, fixture, _1,
+ command->getName(), 200, "Success", encodedParameters);
+
+ manager.onFibRequest(*command);
+
+ BOOST_REQUIRE(fixture->didCallbackFire());
+
+ fixture->resetCallbackFired();
+ face->onReceiveData.clear();
+}
+
+BOOST_AUTO_TEST_CASE(RemoveNextHop)
+{
+ shared_ptr<Face> face1 = make_shared<DummyFace>();
+ shared_ptr<Face> face2 = make_shared<DummyFace>();
+ shared_ptr<Face> face3 = make_shared<DummyFace>();
+
+ addFace(face1);
+ addFace(face2);
+ addFace(face3);
+
+ shared_ptr<InternalFace> face = getInternalFace();
+ FibManager& manager = getFibManager();
+ Fib& fib = getFib();
+
+ shared_ptr<fib::Entry> entry = fib.insert("/hello").first;
+
+ entry->addNextHop(face1, 101);
+ entry->addNextHop(face2, 202);
+ entry->addNextHop(face3, 303);
+
+ testRemoveNextHop(this, manager, fib, face, "/hello", 2);
+ BOOST_REQUIRE(removedNextHopWithCost(fib, "/hello", 3, 202));
+
+ testRemoveNextHop(this, manager, fib, face, "/hello", 3);
+ BOOST_REQUIRE(removedNextHopWithCost(fib, "/hello", 2, 303));
+
+ testRemoveNextHop(this, manager, fib, face, "/hello", 1);
+ // BOOST_REQUIRE(removedNextHopWithCost(fib, "/hello", 1, 101));
+
+ BOOST_CHECK(!static_cast<bool>(getFib().findExactMatch("/hello")));
+}
+
+BOOST_AUTO_TEST_CASE(RemoveFaceNotFound)
+{
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("remove-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 200, "Success", encodedParameters);
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(RemovePrefixNotFound)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+ parameters.setFaceId(1);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("remove-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 200, "Success", encodedParameters);
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(RemoveMissingPrefix)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setFaceId(1);
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("remove-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 400, "Malformed command");
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_AUTO_TEST_CASE(RemoveMissingFaceId)
+{
+ addFace(make_shared<DummyFace>());
+
+ shared_ptr<InternalFace> face = getInternalFace();
+
+ ControlParameters parameters;
+ parameters.setName("/hello");
+
+ Block encodedParameters(parameters.wireEncode());
+
+ Name commandName("/localhost/nfd/fib");
+ commandName.append("remove-nexthop");
+ commandName.append(encodedParameters);
+
+ shared_ptr<Interest> command(make_shared<Interest>(commandName));
+ generateCommand(*command);
+
+ face->onReceiveData +=
+ bind(&FibManagerFixture::validateControlResponse, this, _1,
+ command->getName(), 400, "Malformed command");
+
+ getFibManager().onFibRequest(*command);
+
+ BOOST_REQUIRE(didCallbackFire());
+}
+
+BOOST_FIXTURE_TEST_CASE(TestFibEnumerationRequest, FibManagerFixture)
+{
+ for (int i = 0; i < 87; i++)
+ {
+ Name prefix("/test");
+ prefix.appendSegment(i);
+
+ shared_ptr<DummyFace> dummy1(make_shared<DummyFace>());
+ shared_ptr<DummyFace> dummy2(make_shared<DummyFace>());
+
+ shared_ptr<fib::Entry> entry = m_fib.insert(prefix).first;
+ entry->addNextHop(dummy1, std::numeric_limits<uint64_t>::max() - 1);
+ entry->addNextHop(dummy2, std::numeric_limits<uint64_t>::max() - 2);
+
+ m_referenceEntries.insert(entry);
+ }
+ for (int i = 0; i < 2; i++)
+ {
+ Name prefix("/test2");
+ prefix.appendSegment(i);
+
+ shared_ptr<DummyFace> dummy1(make_shared<DummyFace>());
+ shared_ptr<DummyFace> dummy2(make_shared<DummyFace>());
+
+ shared_ptr<fib::Entry> entry = m_fib.insert(prefix).first;
+ entry->addNextHop(dummy1, std::numeric_limits<uint8_t>::max() - 1);
+ entry->addNextHop(dummy2, std::numeric_limits<uint8_t>::max() - 2);
+
+ m_referenceEntries.insert(entry);
+ }
+
+ ndn::EncodingBuffer buffer;
+
+ m_face->onReceiveData +=
+ bind(&FibEnumerationPublisherFixture::decodeFibEntryBlock, this, _1);
+
+ shared_ptr<Interest> command(make_shared<Interest>("/localhost/nfd/fib/list"));
+
+ m_manager.onFibRequest(*command);
+ BOOST_REQUIRE(m_finished);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nfd