blob: dbb8e5283fda7d3397925225a94d3fd9bf928b5a [file] [log] [blame]
Junxiao Shi67ba8d22015-08-21 21:21:28 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento87fc0f82018-04-11 23:43:51 -04002/*
Ashlesh Gawande1ef93d02022-04-08 00:25:06 -04003 * Copyright (c) 2014-2022, Regents of the University of California,
Junxiao Shi67ba8d22015-08-21 21:21:28 -07004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#include "fw/multicast-strategy.hpp"
Davide Pesavento2cae8ca2019-04-18 20:48:05 -040027#include "common/global.hpp"
Junxiao Shi67ba8d22015-08-21 21:21:28 -070028
29#include "tests/test-common.hpp"
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040030#include "tests/daemon/face/dummy-face.hpp"
Alexander Afanasyev40604e32021-02-17 12:06:26 -050031#include "choose-strategy.hpp"
Davide Pesavento3dade002019-03-19 11:29:56 -060032#include "strategy-tester.hpp"
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070033#include "topology-tester.hpp"
Junxiao Shi67ba8d22015-08-21 21:21:28 -070034
35namespace nfd {
36namespace fw {
37namespace tests {
38
Davide Pesavento14e71f02019-03-28 17:35:25 -040039using MulticastStrategyTester = StrategyTester<MulticastStrategy>;
Junxiao Shi890afe92016-12-15 14:34:34 +000040NFD_REGISTER_STRATEGY(MulticastStrategyTester);
41
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040042class MulticastStrategyFixture : public GlobalIoTimeFixture
Junxiao Shi890afe92016-12-15 14:34:34 +000043{
44protected:
45 MulticastStrategyFixture()
Alexander Afanasyev40604e32021-02-17 12:06:26 -050046 : strategy(choose<MulticastStrategyTester>(forwarder))
47 , face1(make_shared<DummyFace>())
Junxiao Shi890afe92016-12-15 14:34:34 +000048 , face2(make_shared<DummyFace>())
49 , face3(make_shared<DummyFace>())
50 {
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040051 faceTable.add(face1);
52 faceTable.add(face2);
53 faceTable.add(face3);
Junxiao Shi890afe92016-12-15 14:34:34 +000054 }
55
Davide Pesavento03a75f62021-03-09 20:38:38 -050056 bool
57 didSendInterestTo(const Face& face) const
58 {
59 auto it = std::find_if(strategy.sendInterestHistory.begin(),
60 strategy.sendInterestHistory.end(),
61 [&] (const auto& elem) { return elem.outFaceId == face.getId(); });
62 return it != strategy.sendInterestHistory.end();
63 }
64
Junxiao Shi890afe92016-12-15 14:34:34 +000065protected:
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040066 FaceTable faceTable;
67 Forwarder forwarder{faceTable};
Alexander Afanasyev40604e32021-02-17 12:06:26 -050068 MulticastStrategyTester& strategy;
Davide Pesaventoa4abfb02019-10-06 16:02:56 -040069 Fib& fib{forwarder.getFib()};
70 Pit& pit{forwarder.getPit()};
71
Junxiao Shi890afe92016-12-15 14:34:34 +000072 shared_ptr<DummyFace> face1;
73 shared_ptr<DummyFace> face2;
74 shared_ptr<DummyFace> face3;
75};
76
Junxiao Shi5e5e4452015-09-24 16:56:52 -070077BOOST_AUTO_TEST_SUITE(Fw)
Junxiao Shi890afe92016-12-15 14:34:34 +000078BOOST_FIXTURE_TEST_SUITE(TestMulticastStrategy, MulticastStrategyFixture)
Junxiao Shi67ba8d22015-08-21 21:21:28 -070079
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070080BOOST_AUTO_TEST_CASE(Bug5123)
81{
82 fib::Entry& fibEntry = *fib.insert(Name()).first;
83 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
84
85 // Send an Interest from face 1 to face 2
Davide Pesavento03a75f62021-03-09 20:38:38 -050086 auto interest = makeInterest("ndn:/H0D6i5fc");
87 auto pitEntry = pit.insert(*interest).first;
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070088 pitEntry->insertOrUpdateInRecord(*face1, *interest);
89
Davide Pesavento0498ce82021-06-14 02:02:21 -040090 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1, 0), pitEntry);
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070091 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
Davide Pesavento03a75f62021-03-09 20:38:38 -050092 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 1);
Ashlesh Gawandec1d48372020-08-02 22:30:11 -070093
94 // Advance more than default suppression
95 this->advanceClocks(15_ms);
96
97 // Get same interest from face 2 which does not have anywhere to go
98 pitEntry = pit.insert(*interest).first;
99 pitEntry->insertOrUpdateInRecord(*face2, *interest);
100
Davide Pesavento0498ce82021-06-14 02:02:21 -0400101 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face2, 0), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500102 // Since the interest is the same as the one sent out earlier, the PIT entry should not be
103 // rejected, as any data coming back must be able to satisfy the original interest from face 1
Ashlesh Gawandec1d48372020-08-02 22:30:11 -0700104 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
105
106 /*
107 * +---------+ +---------+ +---------+
108 * | nodeA |------------| nodeB |----------| nodeC |
109 * +---------+ 10ms +---------+ 100ms +---------+
110 */
111
112 const Name PRODUCER_PREFIX = "/ndn/edu/nodeC/ping";
113
114 TopologyTester topo;
115 TopologyNode nodeA = topo.addForwarder("A"),
116 nodeB = topo.addForwarder("B"),
117 nodeC = topo.addForwarder("C");
118
119 for (TopologyNode node : {nodeA, nodeB, nodeC}) {
120 topo.setStrategy<MulticastStrategy>(node);
121 }
122
123 shared_ptr<TopologyLink> linkAB = topo.addLink("AB", 10_ms, {nodeA, nodeB}),
124 linkBC = topo.addLink("BC", 100_ms, {nodeB, nodeC});
125
126 shared_ptr<TopologyAppLink> appA = topo.addAppFace("cA", nodeA),
127 appB = topo.addAppFace("cB", nodeB),
128 pingServer = topo.addAppFace("p", nodeC, PRODUCER_PREFIX);
129 topo.addEchoProducer(pingServer->getClientFace());
130 topo.registerPrefix(nodeA, linkAB->getFace(nodeA), PRODUCER_PREFIX, 10);
131 topo.registerPrefix(nodeB, linkAB->getFace(nodeB), PRODUCER_PREFIX, 10);
132 topo.registerPrefix(nodeB, linkBC->getFace(nodeB), PRODUCER_PREFIX, 100);
133
134 Name name(PRODUCER_PREFIX);
135 name.appendTimestamp();
136 interest = makeInterest(name);
137 appA->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
138
139 this->advanceClocks(10_ms, 20_ms);
140
141 // AppB expresses the same interest
142 interest->refreshNonce();
143 appB->getClientFace().expressInterest(*interest, nullptr, nullptr, nullptr);
144 this->advanceClocks(10_ms, 200_ms);
145
146 // Data should have made to appB
147 BOOST_CHECK_EQUAL(linkBC->getFace(nodeB).getCounters().nInData, 1);
148 BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nInData, 0);
149
150 this->advanceClocks(10_ms, 10_ms);
151 // nodeA should have gotten the data successfully
152 BOOST_CHECK_EQUAL(linkAB->getFace(nodeA).getCounters().nInData, 1);
153 BOOST_CHECK_EQUAL(topo.getForwarder(nodeA).getCounters().nUnsolicitedData, 0);
154}
155
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700156BOOST_AUTO_TEST_CASE(Forward2)
157{
Junxiao Shia6de4292016-07-12 02:08:10 +0000158 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000159 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
160 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
161 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700162
Davide Pesavento03a75f62021-03-09 20:38:38 -0500163 auto interest = makeInterest("ndn:/H0D6i5fc");
164 auto pitEntry = pit.insert(*interest).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000165 pitEntry->insertOrUpdateInRecord(*face3, *interest);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700166
Davide Pesavento0498ce82021-06-14 02:02:21 -0400167 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face3, 0), pitEntry);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700168 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
169 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 2);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500170 BOOST_TEST(didSendInterestTo(*face1));
171 BOOST_TEST(didSendInterestTo(*face2));
Ashlesh Gawandee38e2612017-02-25 07:23:41 +0000172
Ashlesh Gawande1ef93d02022-04-08 00:25:06 -0400173 const auto TICK = time::duration_cast<time::nanoseconds>(
174 RetxSuppressionExponential::DEFAULT_INITIAL_INTERVAL) / 10;
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700175
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000176 // downstream retransmits frequently, but the strategy should not send Interests
177 // more often than DEFAULT_MIN_RETX_INTERVAL
178 scheduler::EventId retxFrom4Evt;
179 size_t nSentLast = strategy.sendInterestHistory.size();
Davide Pesavento412c9822021-07-02 00:21:05 -0400180 auto timeSentLast = time::steady_clock::now();
Davide Pesavento87fc0f82018-04-11 23:43:51 -0400181 std::function<void()> periodicalRetxFrom4; // let periodicalRetxFrom4 lambda capture itself
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000182 periodicalRetxFrom4 = [&] {
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000183 pitEntry->insertOrUpdateInRecord(*face3, *interest);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400184 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face3, 0), pitEntry);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700185
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000186 size_t nSent = strategy.sendInterestHistory.size();
187 if (nSent > nSentLast) {
188 // Multicast strategy should multicast the interest to other two faces
189 BOOST_CHECK_EQUAL(nSent - nSentLast, 2);
Davide Pesavento3dade002019-03-19 11:29:56 -0600190 auto timeSent = time::steady_clock::now();
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000191 BOOST_CHECK_GE(timeSent - timeSentLast, TICK * 8);
192 nSentLast = nSent;
193 timeSentLast = timeSent;
194 }
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700195
Davide Pesavento3dade002019-03-19 11:29:56 -0600196 retxFrom4Evt = getScheduler().schedule(TICK * 5, periodicalRetxFrom4);
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000197 };
198 periodicalRetxFrom4();
Ashlesh Gawande1ef93d02022-04-08 00:25:06 -0400199 this->advanceClocks(TICK, RetxSuppressionExponential::DEFAULT_MAX_INTERVAL * 16);
Davide Pesavento3dade002019-03-19 11:29:56 -0600200 retxFrom4Evt.cancel();
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700201}
202
Alexander Afanasyev4400e422021-02-17 11:17:33 -0500203BOOST_AUTO_TEST_CASE(LoopingInterest)
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700204{
Junxiao Shia6de4292016-07-12 02:08:10 +0000205 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000206 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700207
Davide Pesavento03a75f62021-03-09 20:38:38 -0500208 auto interest = makeInterest("ndn:/H0D6i5fc");
209 auto pitEntry = pit.insert(*interest).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000210 pitEntry->insertOrUpdateInRecord(*face1, *interest);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700211
Davide Pesavento0498ce82021-06-14 02:02:21 -0400212 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1, 0), pitEntry);
Alexander Afanasyev4400e422021-02-17 11:17:33 -0500213 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700214 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 0);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700215}
216
Davide Pesavento03a75f62021-03-09 20:38:38 -0500217BOOST_AUTO_TEST_CASE(RetxSuppression)
218{
Ashlesh Gawande1ef93d02022-04-08 00:25:06 -0400219 const auto suppressPeriod = RetxSuppressionExponential::DEFAULT_INITIAL_INTERVAL;
Davide Pesavento03a75f62021-03-09 20:38:38 -0500220 BOOST_ASSERT(suppressPeriod >= 8_ms);
221
222 // Set up the FIB
223 fib::Entry& fibEntry = *fib.insert(Name()).first;
224 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
225 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
226 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
227
228 // Interest arrives from face 1
229 auto interest = makeInterest("/t8ZiSOi3");
230 auto pitEntry = pit.insert(*interest).first;
231 pitEntry->insertOrUpdateInRecord(*face1, *interest);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400232 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1, 0), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500233
234 // forwarded to faces 2 and 3
235 BOOST_TEST(strategy.sendInterestHistory.size() == 2);
236 BOOST_TEST(didSendInterestTo(*face2));
237 BOOST_TEST(didSendInterestTo(*face3));
238 strategy.sendInterestHistory.clear();
239
240 // still within the initial suppression period for face 2 and 3
241 this->advanceClocks(suppressPeriod - 5_ms);
242
243 // Interest arrives from face 2
244 interest->refreshNonce();
245 pitEntry = pit.insert(*interest).first;
246 pitEntry->insertOrUpdateInRecord(*face2, *interest);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400247 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face2, 0), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500248
249 // forwarded only to face 1, suppressed on face 3
250 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
251 BOOST_TEST(didSendInterestTo(*face1));
252 strategy.sendInterestHistory.clear();
253
254 // faces 2 and 3 no longer inside the suppression window
255 this->advanceClocks(7_ms);
256
257 // Interest arrives from face 3
258 interest->refreshNonce();
259 pitEntry = pit.insert(*interest).first;
260 pitEntry->insertOrUpdateInRecord(*face3, *interest);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400261 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face3, 0), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500262
263 // suppressed on face 1, forwarded on face 2 (and suppression window doubles)
264 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
265 BOOST_TEST(didSendInterestTo(*face2));
266 strategy.sendInterestHistory.clear();
267
268 // face 1 exits the suppression period, face 2 still inside
269 this->advanceClocks(2 * suppressPeriod - 2_ms);
270
271 // Interest arrives from face 3
272 interest->refreshNonce();
273 pitEntry = pit.insert(*interest).first;
274 pitEntry->insertOrUpdateInRecord(*face3, *interest);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400275 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face3, 0), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500276
277 // forwarded only to face 1, suppressed on face 2
278 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
279 BOOST_TEST(didSendInterestTo(*face1));
280 strategy.sendInterestHistory.clear();
281
282 // face 2 exits the suppression period
283 this->advanceClocks(3_ms);
284
285 // Interest arrives from face 1
286 interest->refreshNonce();
287 pitEntry = pit.insert(*interest).first;
288 pitEntry->insertOrUpdateInRecord(*face1, *interest);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400289 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1, 0), pitEntry);
Davide Pesavento03a75f62021-03-09 20:38:38 -0500290
291 // forwarded to faces 2 and 3
292 BOOST_TEST(strategy.sendInterestHistory.size() == 2);
293 BOOST_TEST(didSendInterestTo(*face2));
294 BOOST_TEST(didSendInterestTo(*face3));
295 strategy.sendInterestHistory.clear();
296}
297
298BOOST_AUTO_TEST_CASE(NewNextHop)
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500299{
300 fib::Entry& fibEntry = *fib.insert(Name()).first;
301 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
302 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
303
Davide Pesavento03a75f62021-03-09 20:38:38 -0500304 auto interest = makeInterest("ndn:/H0D6i5fc");
305 auto pitEntry = pit.insert(*interest).first;
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500306 pitEntry->insertOrUpdateInRecord(*face1, *interest);
307
Davide Pesavento0498ce82021-06-14 02:02:21 -0400308 strategy.afterReceiveInterest(*interest, FaceEndpoint(*face1, 0), pitEntry);
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500309 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
310 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 1);
311
312 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
313 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
314 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 2);
315}
316
317BOOST_AUTO_TEST_SUITE(LocalhopScope)
318
319class ForwardAsyncFixture : public MulticastStrategyFixture
320{
321protected:
322 shared_ptr<Face> inFace1;
323 shared_ptr<Face> inFace2;
324 shared_ptr<Face> fibFace1;
325 shared_ptr<Face> fibFace2;
326 shared_ptr<Face> newFibFace;
327
328 size_t expectedInterests = 0;
329};
330
331class BasicNonLocal : public ForwardAsyncFixture
332{
333protected:
334 BasicNonLocal()
335 {
336 inFace1 = face1;
337 // inFace2 = nullptr;
338 fibFace1 = face1;
339 fibFace2 = face2;
340 newFibFace = face3;
341 expectedInterests = 0; // anything received on non-local face can only be sent to local face
342 }
343};
344
345class NewFibLocal : public ForwardAsyncFixture
346{
347protected:
348 NewFibLocal()
349 {
350 inFace1 = face1;
351 // inFace2 = nullptr;
352 fibFace1 = face1;
353 fibFace2 = face2;
354 newFibFace = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
355 expectedInterests = 1;
356
357 faceTable.add(newFibFace);
358 }
359};
360
361class InFaceLocal : public ForwardAsyncFixture
362{
363protected:
364 InFaceLocal()
365 {
366 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
367 // inFace2 = nullptr;
368 fibFace1 = face1;
369 fibFace2 = face2;
370 newFibFace = face3;
371 expectedInterests = 1;
372
373 faceTable.add(inFace1);
374 }
375};
376
377class InFaceLocalSameNewFace : public ForwardAsyncFixture
378{
379protected:
380 InFaceLocalSameNewFace()
381 {
382 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
383 // inFace2 = nullptr;
384 fibFace1 = face1;
385 fibFace2 = face2;
386 newFibFace = inFace1;
387 expectedInterests = 0;
388
389 faceTable.add(inFace1);
390 }
391};
392
393class InFaceLocalAdHocSameNewFace : public ForwardAsyncFixture
394{
395protected:
396 InFaceLocalAdHocSameNewFace()
397 {
398 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL,
399 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
400 ndn::nfd::LINK_TYPE_AD_HOC);
401 // inFace2 = nullptr;
402 fibFace1 = face1;
403 fibFace2 = face2;
404 newFibFace = inFace1;
405 expectedInterests = 1;
406
407 faceTable.add(inFace1);
408 }
409};
410
411class InFaceLocalAndNonLocal1 : public ForwardAsyncFixture
412{
413protected:
414 InFaceLocalAndNonLocal1()
415 {
416 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
417 inFace2 = face1;
418 fibFace1 = face1;
419 fibFace2 = face2;
420 newFibFace = face3;
421 expectedInterests = 1;
422
423 faceTable.add(inFace1);
424 }
425};
426
427class InFaceLocalAndNonLocal2 : public ForwardAsyncFixture
428{
429protected:
430 InFaceLocalAndNonLocal2()
431 {
432 inFace1 = face1;
433 inFace2 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
434 fibFace1 = face1;
435 fibFace2 = face2;
436 newFibFace = face3;
437 expectedInterests = 1;
438
439 faceTable.add(inFace2);
440 }
441};
442
443class InFaceSelection1 : public ForwardAsyncFixture
444{
445protected:
446 InFaceSelection1()
447 {
448 inFace1 = face1;
449 // inFace2 = nullptr;
450 fibFace1 = face3;
451 fibFace2 = face2;
452 newFibFace = face1;
453
454 expectedInterests = 0;
455 }
456};
457
458class InFaceSelection2 : public ForwardAsyncFixture
459{
460protected:
461 InFaceSelection2()
462 {
463 inFace1 = face2;
464 inFace2 = face1;
465 fibFace1 = face2;
466 fibFace2 = face3;
467 newFibFace = face1;
468
469 // this test will trigger the check for additional branch, but it
470 // still is not going to pass the localhop check
471 expectedInterests = 0;
472 }
473};
474
475using Tests = boost::mpl::vector<
476 BasicNonLocal,
477 NewFibLocal,
478 InFaceLocal,
479 InFaceLocalSameNewFace,
480 InFaceLocalAdHocSameNewFace,
481 InFaceLocalAndNonLocal1,
482 InFaceLocalAndNonLocal2,
483 InFaceSelection1,
484 InFaceSelection2
485>;
486
487BOOST_FIXTURE_TEST_CASE_TEMPLATE(ForwardAsync, T, Tests, T)
488{
489 fib::Entry& fibEntry = *this->fib.insert(Name("/localhop")).first;
490 this->fib.addOrUpdateNextHop(fibEntry, *this->fibFace1, 0);
491 this->fib.addOrUpdateNextHop(fibEntry, *this->fibFace2, 0);
492
Davide Pesavento03a75f62021-03-09 20:38:38 -0500493 auto interest = makeInterest("ndn:/localhop/H0D6i5fc");
494 auto pitEntry = this->pit.insert(*interest).first;
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500495 pitEntry->insertOrUpdateInRecord(*this->inFace1, *interest);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400496 this->strategy.afterReceiveInterest(*interest, FaceEndpoint(*this->inFace1, 0), pitEntry);
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500497
498 if (this->inFace2 != nullptr) {
Davide Pesavento03a75f62021-03-09 20:38:38 -0500499 auto interest2 = makeInterest("ndn:/localhop/H0D6i5fc");
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500500 pitEntry->insertOrUpdateInRecord(*this->inFace2, *interest2);
Davide Pesavento0498ce82021-06-14 02:02:21 -0400501 this->strategy.afterReceiveInterest(*interest2, FaceEndpoint(*this->inFace2, 0), pitEntry);
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500502 }
503
504 this->strategy.sendInterestHistory.clear();
505 this->fib.addOrUpdateNextHop(fibEntry, *this->newFibFace, 0);
506 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), this->expectedInterests);
507}
508
509BOOST_AUTO_TEST_SUITE_END() // LocalhopScope
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700510BOOST_AUTO_TEST_SUITE_END() // TestMulticastStrategy
511BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700512
513} // namespace tests
514} // namespace fw
515} // namespace nfd