| /* -*- 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, |
| * 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 "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(ref(m_fib), bind(&FibManagerFixture::getFace, this, _1), m_face, m_keyChain) |
| , m_callbackFired(false) |
| { |
| } |
| |
| protected: |
| FibManager m_manager; |
| |
| std::vector<shared_ptr<Face> > m_faces; |
| bool m_callbackFired; |
| ndn::KeyChain m_keyChain; |
| }; |
| |
| 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, command->getName(), 410, "Face not found"); |
| }; |
| |
| getFibManager().onFibRequest(*command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| BOOST_REQUIRE(addedNextHopWithCost(getFib(), "/hello", 0, 101) == false); |
| } |
| |
| BOOST_AUTO_TEST_CASE(AddNextHopVerbImplicitFaceId) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face = getInternalFace(); |
| |
| std::vector<ControlParameters> testedParameters; |
| testedParameters.push_back(ControlParameters().setName("/hello").setCost(101).setFaceId(0)); |
| testedParameters.push_back(ControlParameters().setName("/hello").setCost(101)); |
| |
| for (std::vector<ControlParameters>::iterator parameters = testedParameters.begin(); |
| parameters != testedParameters.end(); ++parameters) { |
| |
| 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 += [this, command, encodedExpectedParameters] (const Data& response) { |
| this->validateControlResponse(response, command->getName(), |
| 200, "Success", encodedExpectedParameters); |
| }; |
| |
| getFibManager().onFibRequest(*command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| BOOST_REQUIRE(addedNextHopWithFace(getFib(), "/hello", 0, 101, getFace(1))); |
| |
| face->onReceiveData.clear(); |
| getFib().erase("/hello"); |
| BOOST_REQUIRE_EQUAL(getFib().size(), 0); |
| } |
| } |
| |
| 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 += [this, command, encodedParameters] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command, resultParameters] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command, encodedParameters] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command, encodedParameters] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command, encodedParameters] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, 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 += [fixture, command, encodedParameters] (const Data& response) { |
| fixture->validateControlResponse(response, 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 += [this, command, encodedParameters] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command, encodedParameters] (const Data& response) { |
| this->validateControlResponse(response, 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 += [this, command] (const Data& response) { |
| this->validateControlResponse(response, command->getName(), 400, "Malformed command"); |
| }; |
| |
| getFibManager().onFibRequest(*command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| BOOST_AUTO_TEST_CASE(RemoveImplicitFaceId) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face = getInternalFace(); |
| |
| std::vector<ControlParameters> testedParameters; |
| testedParameters.push_back(ControlParameters().setName("/hello").setFaceId(0)); |
| testedParameters.push_back(ControlParameters().setName("/hello")); |
| |
| for (std::vector<ControlParameters>::iterator parameters = testedParameters.begin(); |
| parameters != testedParameters.end(); ++parameters) { |
| Block encodedParameters(parameters->wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("remove-nexthop"); |
| commandName.append(encodedParameters); |
| |
| shared_ptr<Interest> command(make_shared<Interest>(commandName)); |
| command->setIncomingFaceId(1); |
| generateCommand(*command); |
| |
| ControlParameters resultParameters; |
| resultParameters.setFaceId(1); |
| resultParameters.setName("/hello"); |
| |
| face->onReceiveData += [this, command, resultParameters] (const Data& response) { |
| this->validateControlResponse(response, command->getName(), |
| 200, "Success", resultParameters.wireEncode()); |
| }; |
| |
| getFibManager().onFibRequest(*command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| |
| face->onReceiveData.clear(); |
| } |
| } |
| |
| 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 |