nlsr: discover Faces from NFD
refs: #2954
Change-Id: I072972d88bce0e1012e96f33577657048b7df1e1
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index 78e0fb9..2cfe46f 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -25,21 +25,21 @@
#include "nlsr.hpp"
#include <ndn-cxx/mgmt/nfd/face-event-notification.hpp>
-#include <ndn-cxx/util/dummy-client-face.hpp>
namespace nlsr {
namespace test {
using std::shared_ptr;
-class NlsrFixture : public UnitTestTimeFixture
+class NlsrFixture : public MockNfdMgmtFixture
{
public:
NlsrFixture()
- : face(std::make_shared<ndn::util::DummyClientFace>(g_ioService))
- , nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
+ : nlsr(g_ioService, g_scheduler, std::ref(*face), g_keyChain)
, lsdb(nlsr.getLsdb())
, neighbors(nlsr.getAdjacencyList())
+ , nSuccessCallbacks(0)
+ , nFailureCallbacks(0)
{
}
@@ -55,10 +55,12 @@
}
public:
- std::shared_ptr<ndn::util::DummyClientFace> face;
Nlsr nlsr;
Lsdb& lsdb;
AdjacencyList& neighbors;
+ uint32_t nSuccessCallbacks;
+ uint32_t nFailureCallbacks;
+
};
BOOST_FIXTURE_TEST_SUITE(TestNlsr, NlsrFixture)
@@ -124,6 +126,92 @@
BOOST_CHECK_EQUAL(rt.getRoutingCalcInterval(), ndn::time::seconds(9));
}
+BOOST_AUTO_TEST_CASE(FaceCreateEvent)
+{
+ // Setting constants for the unit test
+ const uint32_t faceId = 1;
+ const std::string faceUri = "udp4://10.0.0.1:6363";
+ Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(faceUri), 10, Adjacent::STATUS_INACTIVE, 0, 0);
+ BOOST_REQUIRE_EQUAL(nlsr.getAdjacencyList().insert(neighbor), 0);
+
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ // Build, sign, and send the Face Event
+ ndn::nfd::FaceEventNotification event;
+ event.setKind(ndn::nfd::FACE_EVENT_CREATED)
+ .setRemoteUri(faceUri)
+ .setFaceId(faceId);
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
+ data->setContent(event.wireEncode());
+ nlsr.getKeyChain().sign(*data);
+ face->receive(*data);
+
+ // Move the clocks forward so that the Face processes the event.
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ // Need to explicitly provide a FaceUri object, because the
+ // conversion will attempt to create Name objects.
+ auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(faceUri));
+ BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
+ BOOST_CHECK_EQUAL(iterator->getFaceId(), faceId);
+}
+
+BOOST_AUTO_TEST_CASE(FaceCreateEventNoMatch)
+{
+ // Setting constants for the unit test
+ const uint32_t faceId = 1;
+ const std::string eventUri = "udp4://10.0.0.1:6363";
+ const std::string neighborUri = "udp4://10.0.0.2:6363";
+ Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(neighborUri), 10, Adjacent::STATUS_INACTIVE, 0, 0);
+ nlsr.getAdjacencyList().insert(neighbor);
+
+ // Build, sign, and send the Face Event
+ ndn::nfd::FaceEventNotification event;
+ event.setKind(ndn::nfd::FACE_EVENT_CREATED)
+ .setRemoteUri(eventUri)
+ .setFaceId(faceId);
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
+ data->setContent(event.wireEncode());
+ nlsr.getKeyChain().sign(*data);
+ face->receive(*data);
+
+ // Move the clocks forward so that the Face processes the event.
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ // The Face URIs did not match, so this neighbor should be unconfigured.
+ auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(neighborUri));
+ BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
+ BOOST_CHECK_EQUAL(iterator->getFaceId(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(FaceCreateEventAlreadyConfigured)
+{
+ // Setting constants for the unit test
+ const uint32_t eventFaceId = 1;
+ const uint32_t neighborFaceId = 2;
+ const std::string faceUri = "udp4://10.0.0.1:6363";
+ Adjacent neighbor("/ndn/neighborA", ndn::util::FaceUri(faceUri), 10, Adjacent::STATUS_ACTIVE, 0, neighborFaceId);
+ nlsr.getAdjacencyList().insert(neighbor);
+
+ // Build, sign, and send the Face Event
+ ndn::nfd::FaceEventNotification event;
+ event.setKind(ndn::nfd::FACE_EVENT_CREATED)
+ .setRemoteUri(faceUri)
+ .setFaceId(eventFaceId);
+ std::shared_ptr<ndn::Data> data = std::make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
+ data->setContent(event.wireEncode());
+ nlsr.getKeyChain().sign(*data);
+ face->receive(*data);
+
+ // Move the clocks forward so that the Face processes the event.
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ // Since the neighbor was already configured, this (simply erroneous) event should have no effect.
+ auto iterator = nlsr.getAdjacencyList().findAdjacent(ndn::util::FaceUri(faceUri));
+ BOOST_REQUIRE(iterator != nlsr.getAdjacencyList().end());
+ BOOST_CHECK_EQUAL(iterator->getFaceId(), neighborFaceId);
+}
+
BOOST_FIXTURE_TEST_CASE(FaceDestroyEvent, UnitTestTimeFixture)
{
std::shared_ptr<ndn::util::DummyClientFace> face = std::make_shared<ndn::util::DummyClientFace>(g_ioService);
@@ -480,6 +568,134 @@
ndn::util::FaceUri("udp4://10.0.0.2:6363"));
}
+BOOST_AUTO_TEST_CASE(FaceDatasetFetchSuccess)
+{
+ bool hasResult = false;
+ nlsr.m_validator.m_shouldValidate = false;
+
+ nlsr.initializeFaces([&hasResult] (const std::vector<ndn::nfd::FaceStatus>& faces) {
+ hasResult = true;
+ BOOST_CHECK_EQUAL(faces.size(), 2);
+ BOOST_CHECK_EQUAL(faces.front().getFaceId(), 25401);
+ BOOST_CHECK_EQUAL(faces.back().getFaceId(), 25402);
+ },
+ [] (uint32_t code, const std::string& reason) {});
+
+ this->advanceClocks(ndn::time::milliseconds(500));
+
+ ndn::nfd::FaceStatus payload1;
+ payload1.setFaceId(25401);
+ ndn::nfd::FaceStatus payload2;
+ payload2.setFaceId(25402);
+ this->sendDataset("/localhost/nfd/faces/list", payload1, payload2);
+
+ this->advanceClocks(ndn::time::milliseconds(500));
+ BOOST_CHECK(hasResult);
+}
+
+BOOST_AUTO_TEST_CASE(FaceDatasetFetchFailure)
+{
+ nlsr.m_validator.m_shouldValidate = false;
+ nlsr.initializeFaces([](const std::vector<ndn::nfd::FaceStatus>& faces) {},
+ [this](uint32_t code, const std::string& reason){
+ this->nFailureCallbacks++;
+ });
+ this->advanceClocks(ndn::time::milliseconds(500));
+
+ ndn::Name payload;
+ this->sendDataset("/localhost/nfd/faces/list", payload);
+ this->advanceClocks(ndn::time::milliseconds(500));
+
+ BOOST_CHECK_EQUAL(nFailureCallbacks, 1);
+ BOOST_CHECK_EQUAL(nSuccessCallbacks, 0);
+}
+
+BOOST_AUTO_TEST_CASE(FaceDatasetProcess)
+{
+ Adjacent neighborA("/ndn/neighborA", ndn::util::FaceUri("udp4://192.168.0.100:6363"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
+ neighbors.insert(neighborA);
+
+ Adjacent neighborB("/ndn/neighborB", ndn::util::FaceUri("udp4://192.168.0.101:6363"), 10, Adjacent::STATUS_INACTIVE, 0, 0);
+ neighbors.insert(neighborB);
+
+ ndn::nfd::FaceStatus payload1;
+ payload1.setFaceId(1)
+ .setRemoteUri("udp4://192.168.0.100:6363");
+ ndn::nfd::FaceStatus payload2;
+ payload2.setFaceId(2)
+ .setRemoteUri("udp4://192.168.0.101:6363");
+ std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload1, payload2};
+
+ nlsr.processFaceDataset(faceStatuses);
+ this->advanceClocks(ndn::time::milliseconds(100));
+
+ AdjacencyList adjList = nlsr.getAdjacencyList();
+
+ BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), payload1.getFaceId());
+ BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborB").getFaceId(), payload2.getFaceId());
+}
+
+BOOST_AUTO_TEST_CASE(UnconfiguredNeighbor)
+{
+ Adjacent neighborA("/ndn/neighborA", ndn::util::FaceUri("udp4://192.168.0.100:6363"), 25, Adjacent::STATUS_INACTIVE, 0, 0);
+ neighbors.insert(neighborA);
+
+ ndn::nfd::FaceStatus payload;
+ payload.setFaceId(1)
+ .setRemoteUri("udp4://192.168.0.101:6363"); // Note dissimilar Face URI.
+ std::vector<ndn::nfd::FaceStatus> faceStatuses = {payload};
+
+ nlsr.processFaceDataset(faceStatuses);
+ this->advanceClocks(ndn::time::milliseconds(100));
+
+ AdjacencyList adjList = nlsr.getAdjacencyList();
+
+ BOOST_CHECK_EQUAL(adjList.getAdjacent("/ndn/neighborA").getFaceId(), 0);
+}
+
+BOOST_AUTO_TEST_CASE(FaceDatasetPeriodicFetch)
+{
+ int nNameMatches = 0;
+ ndn::Name datasetPrefix("/localhost/nfd/faces/list");
+ ndn::nfd::CommandOptions options;
+ ndn::time::milliseconds defaultTimeout = options.getTimeout();
+
+ ndn::time::seconds fetchInterval(1);
+ ConfParameter& conf = nlsr.getConfParameter();
+ conf.setFaceDatasetFetchInterval(fetchInterval);
+ conf.setFaceDatasetFetchTries(0);
+
+ nlsr.initializeFaces(std::bind(&Nlsr::processFaceDataset, &nlsr, _1),
+ std::bind(&Nlsr::onFaceDatasetFetchTimeout, &nlsr, _1, _2, 0));
+
+ // Elapse the default timeout time of the interest.
+ this->advanceClocks(defaultTimeout);
+
+ // Check that we have one interest for face list in the sent interests.
+ for (const ndn::Interest& interest : face->sentInterests) {
+ if (datasetPrefix.isPrefixOf(interest.getName())) {
+ nNameMatches++;
+ }
+ }
+ BOOST_CHECK_EQUAL(nNameMatches, 1);
+
+ // Elapse the clock by the reschedule time (that we set)
+ this->advanceClocks(fetchInterval);
+ // Elapse the default timeout on the interest.
+ this->advanceClocks(defaultTimeout);
+ // Plus a little more to let the events process.
+ this->advanceClocks(ndn::time::seconds(1));
+
+ // Check that we now have two interests
+ nNameMatches = 0;
+ for (const ndn::Interest& interest : face->sentInterests) {
+ if (datasetPrefix.isPrefixOf(interest.getName())) {
+ nNameMatches++;
+ }
+ }
+ BOOST_CHECK_EQUAL(nNameMatches, 2);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} // namespace test