Don't build Adjacency LSA when destroyed face belongs to INACTIVE node
refs: #2733
Change-Id: I2a53bce876486980b380e9d8226b410bc754b034
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index 74a3f47..ed41d9b 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -21,6 +21,7 @@
**/
#include "test-common.hpp"
+#include "control-commands.hpp"
#include "dummy-face.hpp"
#include "nlsr.hpp"
@@ -183,6 +184,101 @@
BOOST_CHECK(rtEntry == nullptr);
}
+// Bug #2733
+// This test checks that when a face for an inactive node is destroyed, an
+// Adjacency LSA build does not postpone the LSA refresh and cause RIB
+// entries for other nodes' name prefixes to not be refreshed.
+//
+// This test is invalid when Issue #2732 is implemented since an Adjacency LSA
+// refresh will not cause RIB entries for other nodes' name prefixes to be refreshed.
+BOOST_FIXTURE_TEST_CASE(FaceDestroyEventInactive, UnitTestTimeFixture)
+{
+ shared_ptr<ndn::util::DummyClientFace> face = ndn::util::makeDummyClientFace(g_ioService);
+ Nlsr nlsr(g_ioService, g_scheduler, ndn::ref(*face));
+ Lsdb& lsdb = nlsr.getLsdb();
+
+ // Simulate loading configuration file
+ ConfParameter& conf = nlsr.getConfParameter();
+ conf.setNetwork("/ndn");
+ conf.setSiteName("/site");
+ conf.setRouterName("/%C1.router/this-router");
+ conf.setFirstHelloInterval(0);
+ conf.setAdjLsaBuildInterval(0);
+ conf.setRoutingCalcInterval(0);
+
+ // Add neighbors
+ AdjacencyList& neighbors = nlsr.getAdjacencyList();
+
+ uint64_t destroyFaceId = 128;
+
+ // Create an inactive neighbor whose Face will be destroyed
+ Adjacent failNeighbor("/ndn/neighborA", "uri://faceA", 10, Adjacent::STATUS_INACTIVE, 3,
+ destroyFaceId);
+ neighbors.insert(failNeighbor);
+
+ // Create an additional active neighbor so an adjacency LSA can be built
+ Adjacent otherNeighbor("/ndn/neighborB", "uri://faceB", 25, Adjacent::STATUS_ACTIVE, 0, 256);
+ neighbors.insert(otherNeighbor);
+
+ // Add a name for the neighbor to advertise
+ NamePrefixList nameList;
+ ndn::Name nameToAdvertise("/ndn/neighborB/name");
+ nameList.insert(nameToAdvertise);
+
+ NameLsa nameLsa("/ndn/neighborB", "name", 25, ndn::time::system_clock::now(), nameList);
+ lsdb.installNameLsa(nameLsa);
+
+ nlsr.initialize();
+
+ // Simulate successful HELLO responses from neighbor B
+ lsdb.scheduleAdjLsaBuild();
+
+ // Run the scheduler to build an adjacency LSA
+ this->advanceClocks(ndn::time::milliseconds(1));
+
+ ndn::Name key = ndn::Name(nlsr.getConfParameter().getRouterPrefix()).append(AdjLsa::TYPE_STRING);
+ AdjLsa* lsa = lsdb.findAdjLsa(key);
+ BOOST_REQUIRE(lsa != nullptr);
+
+ // Cancel previous LSA expiration event
+ g_scheduler.cancelEvent(lsa->getExpiringEventId());
+
+ // Set expiration time for own Adjacency LSA to earlier value for unit-test
+ //
+ // Expiration time is negative to offset the GRACE_PERIOD (10 seconds) automatically applied
+ // to expiration times
+ ndn::EventId id = lsdb.scheduleAdjLsaExpiration(key, lsa->getLsSeqNo(), -ndn::time::seconds(9));
+ lsa->setExpiringEventId(id);
+
+ // Generate a FaceEventDestroyed notification
+ ndn::nfd::FaceEventNotification event;
+ event.setKind(ndn::nfd::FACE_EVENT_DESTROYED)
+ .setFaceId(destroyFaceId);
+
+ shared_ptr<ndn::Data> data = make_shared<ndn::Data>("/localhost/nfd/faces/events/%FE%00");
+ data->setContent(event.wireEncode());
+ nlsr.getKeyChain().sign(*data);
+
+ // Receive the FaceEventDestroyed notification
+ face->receive(*data);
+
+ // Run the scheduler to expire the Adjacency LSA. The expiration should refresh the RIB
+ // entries associated with Neighbor B's advertised prefix.
+ face->sentInterests.clear();
+ this->advanceClocks(ndn::time::seconds(1));
+
+ // The Face should have two sent Interests: the face event and a RIB registration
+ BOOST_REQUIRE(face->sentInterests.size() > 0);
+ const ndn::Interest& interest = face->sentInterests.back();
+
+ ndn::nfd::ControlParameters parameters;
+ ndn::Name::Component verb;
+ BOOST_REQUIRE_NO_THROW(extractRibCommandParameters(interest, verb, parameters));
+
+ BOOST_CHECK_EQUAL(verb, ndn::Name::Component("register"));
+ BOOST_CHECK_EQUAL(parameters.getName(), nameToAdvertise);
+}
+
BOOST_AUTO_TEST_SUITE_END()
} //namespace test