blob: a75bf305982110381e3856878adc5fc98c6a726f [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/*
Alexander Afanasyev4400e422021-02-17 11:17:33 -05003 * Copyright (c) 2014-2021, 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
90 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest, pitEntry);
91 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
101 strategy.afterReceiveInterest(FaceEndpoint(*face2, 0), *interest, 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
ashiqopuc7079482019-02-20 05:34:37 +0000167 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest, 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
Davide Pesavento03a75f62021-03-09 20:38:38 -0500173 const auto TICK = time::duration_cast<time::nanoseconds>(MulticastStrategy::RETX_SUPPRESSION_INITIAL) / 10;
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700174
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000175 // downstream retransmits frequently, but the strategy should not send Interests
176 // more often than DEFAULT_MIN_RETX_INTERVAL
177 scheduler::EventId retxFrom4Evt;
178 size_t nSentLast = strategy.sendInterestHistory.size();
179 time::steady_clock::TimePoint timeSentLast = time::steady_clock::now();
Davide Pesavento87fc0f82018-04-11 23:43:51 -0400180 std::function<void()> periodicalRetxFrom4; // let periodicalRetxFrom4 lambda capture itself
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000181 periodicalRetxFrom4 = [&] {
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000182 pitEntry->insertOrUpdateInRecord(*face3, *interest);
ashiqopuc7079482019-02-20 05:34:37 +0000183 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest, pitEntry);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700184
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000185 size_t nSent = strategy.sendInterestHistory.size();
186 if (nSent > nSentLast) {
187 // Multicast strategy should multicast the interest to other two faces
188 BOOST_CHECK_EQUAL(nSent - nSentLast, 2);
Davide Pesavento3dade002019-03-19 11:29:56 -0600189 auto timeSent = time::steady_clock::now();
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000190 BOOST_CHECK_GE(timeSent - timeSentLast, TICK * 8);
191 nSentLast = nSent;
192 timeSentLast = timeSent;
193 }
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700194
Davide Pesavento3dade002019-03-19 11:29:56 -0600195 retxFrom4Evt = getScheduler().schedule(TICK * 5, periodicalRetxFrom4);
Ashlesh Gawandeecdbe5f2017-03-04 03:08:24 +0000196 };
197 periodicalRetxFrom4();
198 this->advanceClocks(TICK, MulticastStrategy::RETX_SUPPRESSION_MAX * 16);
Davide Pesavento3dade002019-03-19 11:29:56 -0600199 retxFrom4Evt.cancel();
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700200}
201
Alexander Afanasyev4400e422021-02-17 11:17:33 -0500202BOOST_AUTO_TEST_CASE(LoopingInterest)
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700203{
Junxiao Shia6de4292016-07-12 02:08:10 +0000204 fib::Entry& fibEntry = *fib.insert(Name()).first;
Ju Pand8315bf2019-07-31 06:59:07 +0000205 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700206
Davide Pesavento03a75f62021-03-09 20:38:38 -0500207 auto interest = makeInterest("ndn:/H0D6i5fc");
208 auto pitEntry = pit.insert(*interest).first;
Md Ashiqur Rahmanc88d2d42019-08-28 20:19:47 +0000209 pitEntry->insertOrUpdateInRecord(*face1, *interest);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700210
ashiqopuc7079482019-02-20 05:34:37 +0000211 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest, pitEntry);
Alexander Afanasyev4400e422021-02-17 11:17:33 -0500212 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700213 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 0);
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700214}
215
Davide Pesavento03a75f62021-03-09 20:38:38 -0500216BOOST_AUTO_TEST_CASE(RetxSuppression)
217{
218 const auto suppressPeriod = MulticastStrategy::RETX_SUPPRESSION_INITIAL;
219 BOOST_ASSERT(suppressPeriod >= 8_ms);
220
221 // Set up the FIB
222 fib::Entry& fibEntry = *fib.insert(Name()).first;
223 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
224 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
225 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
226
227 // Interest arrives from face 1
228 auto interest = makeInterest("/t8ZiSOi3");
229 auto pitEntry = pit.insert(*interest).first;
230 pitEntry->insertOrUpdateInRecord(*face1, *interest);
231 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest, pitEntry);
232
233 // forwarded to faces 2 and 3
234 BOOST_TEST(strategy.sendInterestHistory.size() == 2);
235 BOOST_TEST(didSendInterestTo(*face2));
236 BOOST_TEST(didSendInterestTo(*face3));
237 strategy.sendInterestHistory.clear();
238
239 // still within the initial suppression period for face 2 and 3
240 this->advanceClocks(suppressPeriod - 5_ms);
241
242 // Interest arrives from face 2
243 interest->refreshNonce();
244 pitEntry = pit.insert(*interest).first;
245 pitEntry->insertOrUpdateInRecord(*face2, *interest);
246 strategy.afterReceiveInterest(FaceEndpoint(*face2, 0), *interest, pitEntry);
247
248 // forwarded only to face 1, suppressed on face 3
249 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
250 BOOST_TEST(didSendInterestTo(*face1));
251 strategy.sendInterestHistory.clear();
252
253 // faces 2 and 3 no longer inside the suppression window
254 this->advanceClocks(7_ms);
255
256 // Interest arrives from face 3
257 interest->refreshNonce();
258 pitEntry = pit.insert(*interest).first;
259 pitEntry->insertOrUpdateInRecord(*face3, *interest);
260 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest, pitEntry);
261
262 // suppressed on face 1, forwarded on face 2 (and suppression window doubles)
263 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
264 BOOST_TEST(didSendInterestTo(*face2));
265 strategy.sendInterestHistory.clear();
266
267 // face 1 exits the suppression period, face 2 still inside
268 this->advanceClocks(2 * suppressPeriod - 2_ms);
269
270 // Interest arrives from face 3
271 interest->refreshNonce();
272 pitEntry = pit.insert(*interest).first;
273 pitEntry->insertOrUpdateInRecord(*face3, *interest);
274 strategy.afterReceiveInterest(FaceEndpoint(*face3, 0), *interest, pitEntry);
275
276 // forwarded only to face 1, suppressed on face 2
277 BOOST_TEST(strategy.sendInterestHistory.size() == 1);
278 BOOST_TEST(didSendInterestTo(*face1));
279 strategy.sendInterestHistory.clear();
280
281 // face 2 exits the suppression period
282 this->advanceClocks(3_ms);
283
284 // Interest arrives from face 1
285 interest->refreshNonce();
286 pitEntry = pit.insert(*interest).first;
287 pitEntry->insertOrUpdateInRecord(*face1, *interest);
288 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest, pitEntry);
289
290 // forwarded to faces 2 and 3
291 BOOST_TEST(strategy.sendInterestHistory.size() == 2);
292 BOOST_TEST(didSendInterestTo(*face2));
293 BOOST_TEST(didSendInterestTo(*face3));
294 strategy.sendInterestHistory.clear();
295}
296
297BOOST_AUTO_TEST_CASE(NewNextHop)
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500298{
299 fib::Entry& fibEntry = *fib.insert(Name()).first;
300 fib.addOrUpdateNextHop(fibEntry, *face1, 0);
301 fib.addOrUpdateNextHop(fibEntry, *face2, 0);
302
Davide Pesavento03a75f62021-03-09 20:38:38 -0500303 auto interest = makeInterest("ndn:/H0D6i5fc");
304 auto pitEntry = pit.insert(*interest).first;
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500305 pitEntry->insertOrUpdateInRecord(*face1, *interest);
306
307 strategy.afterReceiveInterest(FaceEndpoint(*face1, 0), *interest, pitEntry);
308 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
309 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 1);
310
311 fib.addOrUpdateNextHop(fibEntry, *face3, 0);
312 BOOST_CHECK_EQUAL(strategy.rejectPendingInterestHistory.size(), 0);
313 BOOST_CHECK_EQUAL(strategy.sendInterestHistory.size(), 2);
314}
315
316BOOST_AUTO_TEST_SUITE(LocalhopScope)
317
318class ForwardAsyncFixture : public MulticastStrategyFixture
319{
320protected:
321 shared_ptr<Face> inFace1;
322 shared_ptr<Face> inFace2;
323 shared_ptr<Face> fibFace1;
324 shared_ptr<Face> fibFace2;
325 shared_ptr<Face> newFibFace;
326
327 size_t expectedInterests = 0;
328};
329
330class BasicNonLocal : public ForwardAsyncFixture
331{
332protected:
333 BasicNonLocal()
334 {
335 inFace1 = face1;
336 // inFace2 = nullptr;
337 fibFace1 = face1;
338 fibFace2 = face2;
339 newFibFace = face3;
340 expectedInterests = 0; // anything received on non-local face can only be sent to local face
341 }
342};
343
344class NewFibLocal : public ForwardAsyncFixture
345{
346protected:
347 NewFibLocal()
348 {
349 inFace1 = face1;
350 // inFace2 = nullptr;
351 fibFace1 = face1;
352 fibFace2 = face2;
353 newFibFace = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
354 expectedInterests = 1;
355
356 faceTable.add(newFibFace);
357 }
358};
359
360class InFaceLocal : public ForwardAsyncFixture
361{
362protected:
363 InFaceLocal()
364 {
365 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
366 // inFace2 = nullptr;
367 fibFace1 = face1;
368 fibFace2 = face2;
369 newFibFace = face3;
370 expectedInterests = 1;
371
372 faceTable.add(inFace1);
373 }
374};
375
376class InFaceLocalSameNewFace : public ForwardAsyncFixture
377{
378protected:
379 InFaceLocalSameNewFace()
380 {
381 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
382 // inFace2 = nullptr;
383 fibFace1 = face1;
384 fibFace2 = face2;
385 newFibFace = inFace1;
386 expectedInterests = 0;
387
388 faceTable.add(inFace1);
389 }
390};
391
392class InFaceLocalAdHocSameNewFace : public ForwardAsyncFixture
393{
394protected:
395 InFaceLocalAdHocSameNewFace()
396 {
397 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL,
398 ndn::nfd::FACE_PERSISTENCY_PERSISTENT,
399 ndn::nfd::LINK_TYPE_AD_HOC);
400 // inFace2 = nullptr;
401 fibFace1 = face1;
402 fibFace2 = face2;
403 newFibFace = inFace1;
404 expectedInterests = 1;
405
406 faceTable.add(inFace1);
407 }
408};
409
410class InFaceLocalAndNonLocal1 : public ForwardAsyncFixture
411{
412protected:
413 InFaceLocalAndNonLocal1()
414 {
415 inFace1 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
416 inFace2 = face1;
417 fibFace1 = face1;
418 fibFace2 = face2;
419 newFibFace = face3;
420 expectedInterests = 1;
421
422 faceTable.add(inFace1);
423 }
424};
425
426class InFaceLocalAndNonLocal2 : public ForwardAsyncFixture
427{
428protected:
429 InFaceLocalAndNonLocal2()
430 {
431 inFace1 = face1;
432 inFace2 = make_shared<DummyFace>("dummy://", "dummy://", ndn::nfd::FACE_SCOPE_LOCAL);
433 fibFace1 = face1;
434 fibFace2 = face2;
435 newFibFace = face3;
436 expectedInterests = 1;
437
438 faceTable.add(inFace2);
439 }
440};
441
442class InFaceSelection1 : public ForwardAsyncFixture
443{
444protected:
445 InFaceSelection1()
446 {
447 inFace1 = face1;
448 // inFace2 = nullptr;
449 fibFace1 = face3;
450 fibFace2 = face2;
451 newFibFace = face1;
452
453 expectedInterests = 0;
454 }
455};
456
457class InFaceSelection2 : public ForwardAsyncFixture
458{
459protected:
460 InFaceSelection2()
461 {
462 inFace1 = face2;
463 inFace2 = face1;
464 fibFace1 = face2;
465 fibFace2 = face3;
466 newFibFace = face1;
467
468 // this test will trigger the check for additional branch, but it
469 // still is not going to pass the localhop check
470 expectedInterests = 0;
471 }
472};
473
474using Tests = boost::mpl::vector<
475 BasicNonLocal,
476 NewFibLocal,
477 InFaceLocal,
478 InFaceLocalSameNewFace,
479 InFaceLocalAdHocSameNewFace,
480 InFaceLocalAndNonLocal1,
481 InFaceLocalAndNonLocal2,
482 InFaceSelection1,
483 InFaceSelection2
484>;
485
486BOOST_FIXTURE_TEST_CASE_TEMPLATE(ForwardAsync, T, Tests, T)
487{
488 fib::Entry& fibEntry = *this->fib.insert(Name("/localhop")).first;
489 this->fib.addOrUpdateNextHop(fibEntry, *this->fibFace1, 0);
490 this->fib.addOrUpdateNextHop(fibEntry, *this->fibFace2, 0);
491
Davide Pesavento03a75f62021-03-09 20:38:38 -0500492 auto interest = makeInterest("ndn:/localhop/H0D6i5fc");
493 auto pitEntry = this->pit.insert(*interest).first;
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500494 pitEntry->insertOrUpdateInRecord(*this->inFace1, *interest);
495 this->strategy.afterReceiveInterest(FaceEndpoint(*this->inFace1, 0), *interest, pitEntry);
496
497 if (this->inFace2 != nullptr) {
Davide Pesavento03a75f62021-03-09 20:38:38 -0500498 auto interest2 = makeInterest("ndn:/localhop/H0D6i5fc");
Alexander Afanasyev40604e32021-02-17 12:06:26 -0500499 pitEntry->insertOrUpdateInRecord(*this->inFace2, *interest2);
500 this->strategy.afterReceiveInterest(FaceEndpoint(*this->inFace2, 0), *interest2, pitEntry);
501 }
502
503 this->strategy.sendInterestHistory.clear();
504 this->fib.addOrUpdateNextHop(fibEntry, *this->newFibFace, 0);
505 BOOST_CHECK_EQUAL(this->strategy.sendInterestHistory.size(), this->expectedInterests);
506}
507
508BOOST_AUTO_TEST_SUITE_END() // LocalhopScope
Junxiao Shi5e5e4452015-09-24 16:56:52 -0700509BOOST_AUTO_TEST_SUITE_END() // TestMulticastStrategy
510BOOST_AUTO_TEST_SUITE_END() // Fw
Junxiao Shi67ba8d22015-08-21 21:21:28 -0700511
512} // namespace tests
513} // namespace fw
514} // namespace nfd