| /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| /** |
| * Copyright (C) 2014 Named Data Networking Project |
| * See COPYING for copyright and distribution information. |
| */ |
| |
| #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/face/dummy-face.hpp" |
| |
| #include "tests/test-common.hpp" |
| |
| namespace nfd { |
| namespace tests { |
| |
| NFD_LOG_INIT("FibManagerTest"); |
| |
| class FibManagerFixture : protected BaseFixture |
| { |
| public: |
| |
| FibManagerFixture() |
| : m_callbackFired(false) |
| { |
| |
| } |
| |
| 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(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; |
| } |
| |
| private: |
| std::vector<shared_ptr<Face> > m_faces; |
| bool m_callbackFired; |
| }; |
| |
| BOOST_FIXTURE_TEST_SUITE(MgmtFibManager, 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(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| Interest command("/localhost/nfd/fib"); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| command.getName(), 400, "Malformed command"); |
| |
| face->sendInterest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| BOOST_AUTO_TEST_CASE(MalformedCommmand) |
| { |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| BOOST_REQUIRE(didCallbackFire() == false); |
| |
| Interest command("/localhost/nfd/fib"); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| command.getName(), 400, "Malformed command"); |
| |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| BOOST_AUTO_TEST_CASE(UnsupportedVerb) |
| { |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1); |
| options.setCost(1); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("unsupported"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 501, "Unsupported command"); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| BOOST_AUTO_TEST_CASE(UnsignedCommand) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1); |
| options.setCost(101); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 404, "Prefix not found"); |
| /// \todo enable once sig checking implemented |
| // bind(&FibManagerFixture::validateControlResponse, this, _1, 401, "Signature required"); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| BOOST_REQUIRE(!addedNextHopWithCost(fib, "/hello", 0, 101)); |
| } |
| |
| BOOST_AUTO_TEST_CASE(UnauthorizedCommand) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1); |
| options.setCost(101); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 404, "Prefix not found"); |
| /// \todo enable once sig checking implemented |
| // bind(&FibManagerFixture::validateControlResponse, this, _1, 403, "Unauthorized command"); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| BOOST_REQUIRE(!addedNextHopWithCost(fib, "/hello", 0, 101)); |
| } |
| |
| BOOST_AUTO_TEST_CASE(BadOptionParse) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append("NotReallyOptions"); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 400, "Malformed command"); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| BOOST_AUTO_TEST_CASE(UnknownFaceId) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1000); |
| options.setCost(101); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 404, "Face not found"); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| BOOST_REQUIRE(addedNextHopWithCost(fib, "/hello", 0, 101) == false); |
| } |
| |
| BOOST_AUTO_TEST_CASE(TestImplicitFaceId) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(0); |
| options.setCost(101); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append(encodedOptions); |
| |
| FibManagementOptions expectedOptions; |
| expectedOptions.setName("/hello"); |
| expectedOptions.setFaceId(1); |
| expectedOptions.setCost(101); |
| |
| Block encodedExpectedOptions(expectedOptions.wireEncode()); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 200, "Success", encodedExpectedOptions); |
| |
| fib.insert("/hello"); |
| |
| Interest command(commandName); |
| command.setIncomingFaceId(1); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| BOOST_REQUIRE(addedNextHopWithFace(fib, "/hello", 0, 101, getFace(1))); |
| } |
| |
| BOOST_AUTO_TEST_CASE(AddNextHopVerbInitialAdd) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1); |
| options.setCost(101); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 200, "Success", encodedOptions); |
| |
| fib.insert("/hello"); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| BOOST_REQUIRE(addedNextHopWithCost(fib, "/hello", 0, 101)); |
| } |
| |
| BOOST_AUTO_TEST_CASE(AddNextHopVerbAddToExisting) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| fib.insert("/hello"); |
| |
| for (int i = 1; i <= 2; i++) |
| { |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1); |
| options.setCost(100 + i); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 200, "Success", encodedOptions); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| BOOST_REQUIRE(didCallbackFire()); |
| resetCallbackFired(); |
| |
| shared_ptr<fib::Entry> entry = fib.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(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, |
| this, _1), |
| face); |
| |
| fib.insert("/hello"); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1); |
| |
| { |
| options.setCost(1); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 200, "Success", encodedOptions); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| resetCallbackFired(); |
| face->onReceiveData.clear(); |
| |
| { |
| options.setCost(102); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("add-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 200, "Success", encodedOptions); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| shared_ptr<fib::Entry> entry = fib.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(Insert) |
| { |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| { |
| FibManagementOptions options; |
| options.setName("/hello"); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("insert"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 200, "Success", encodedOptions); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| } |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| |
| shared_ptr<fib::Entry> entry = fib.findExactMatch("/hello"); |
| if (static_cast<bool>(entry)) |
| { |
| const fib::NextHopList& hops = entry->getNextHops(); |
| BOOST_CHECK_EQUAL(hops.size(), 0); |
| } |
| |
| resetCallbackFired(); |
| |
| { |
| FibManagementOptions options; |
| options.setName("/hello"); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("insert"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 200, "Success", encodedOptions); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| } |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| |
| entry = fib.findExactMatch("/hello"); |
| if (static_cast<bool>(entry)) |
| { |
| const fib::NextHopList& hops = entry->getNextHops(); |
| BOOST_CHECK_EQUAL(hops.size(), 0); |
| } |
| |
| } |
| |
| void |
| testRemove(FibManagerFixture* fixture, |
| FibManager& manager, |
| Fib& fib, |
| shared_ptr<Face> face, |
| const Name& target) |
| { |
| FibManagementOptions options; |
| options.setName(target); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("delete"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, fixture, _1, |
| commandName, 200, "Success", encodedOptions); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(fixture->didCallbackFire()); |
| |
| if (static_cast<bool>(fib.findExactMatch(target))) |
| { |
| BOOST_FAIL("Found \"removed\" prefix"); |
| } |
| face->onReceiveData.clear(); |
| } |
| |
| BOOST_AUTO_TEST_CASE(Delete) |
| { |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| fib.insert("/a"); |
| fib.insert("/a/b"); |
| fib.insert("/a/b/c"); |
| |
| testRemove(this, manager, fib, face, "/"); |
| |
| if (!static_cast<bool>(fib.findExactMatch("/a")) || |
| !static_cast<bool>(fib.findExactMatch("/a/b")) || |
| !static_cast<bool>(fib.findExactMatch("/a/b/c"))) |
| { |
| BOOST_FAIL("Removed incorrect entry"); |
| } |
| |
| testRemove(this, manager, fib, face, "/a/b"); |
| |
| if (!static_cast<bool>(fib.findExactMatch("/a")) || |
| !static_cast<bool>(fib.findExactMatch("/a/b/c"))) |
| { |
| BOOST_FAIL("Removed incorrect entry"); |
| } |
| |
| testRemove(this, manager, fib, face, "/a/b/c"); |
| |
| if (!static_cast<bool>(fib.findExactMatch("/a"))) |
| { |
| BOOST_FAIL("Removed incorrect entry"); |
| } |
| |
| testRemove(this, manager, fib, face, "/a"); |
| |
| testRemove(this, manager, fib, face, "/does/not/exist"); |
| } |
| |
| 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(FibManagerFixture* fixture, |
| FibManager& manager, |
| Fib& fib, |
| shared_ptr<Face> face, |
| const Name& targetName, |
| FaceId targetFace) |
| { |
| FibManagementOptions options; |
| options.setName(targetName); |
| options.setFaceId(targetFace); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("remove-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, fixture, _1, |
| commandName, 200, "Success", encodedOptions); |
| |
| Interest command(commandName); |
| 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(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| 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)); |
| |
| if (!static_cast<bool>(fib.findExactMatch("/hello"))) |
| { |
| BOOST_FAIL("removed entry after removing all next hops"); |
| } |
| |
| } |
| |
| BOOST_AUTO_TEST_CASE(RemoveNoFace) |
| { |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("remove-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 404, "Face not found"); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| BOOST_AUTO_TEST_CASE(RemoveNoPrefix) |
| { |
| addFace(make_shared<DummyFace>()); |
| |
| shared_ptr<InternalFace> face(make_shared<InternalFace>()); |
| Fib fib; |
| FibManager manager(fib, |
| bind(&FibManagerFixture::getFace, this, _1), |
| face); |
| |
| FibManagementOptions options; |
| options.setName("/hello"); |
| options.setFaceId(1); |
| |
| Block encodedOptions(options.wireEncode()); |
| |
| Name commandName("/localhost/nfd/fib"); |
| commandName.append("remove-nexthop"); |
| commandName.append(encodedOptions); |
| |
| face->onReceiveData += |
| bind(&FibManagerFixture::validateControlResponse, this, _1, |
| commandName, 404, "Prefix not found"); |
| |
| Interest command(commandName); |
| manager.onFibRequest(command); |
| |
| BOOST_REQUIRE(didCallbackFire()); |
| } |
| |
| BOOST_AUTO_TEST_SUITE_END() |
| |
| } // namespace tests |
| } // namespace nfd |